在不提供所有权的情况下公开 shared_pointers 的矢量
Exposing a vector of shared_pointers without giving ownership
我有一个包含共享指针向量的简单 class:
class Bar {
public:
/* stuff */
private:
std::vector<std::shared_ptr<Foo>> foos;
};
我希望通过 getFoos()
函数公开我的 foos
,该函数不会共享对象的所有权。一种方法是:
std::vector<std::reference_wrapper<Foo>> Bar::getFoos() const {
std::vector<std::reference_wrapper<Foo>> fooRefs;
fooRefs.reserve(foos.size());
for (auto& ptr : foos) {
fooRefs.push_back(std::ref(*ptr));
}
return fooRefs;
}
但这很丑陋。另外,我很可能需要缓存结果,因为这个函数经常被调用。更复杂,更丑陋。
是否有 cleaner/better 方法来处理这个问题?
可能是范围视图 range-v3:
class Bar {
public:
/* stuff */
auto get_foos() const { return foos | ranges::views::indirect; }
private:
std::vector<std::shared_pointer<Foo>> foos;
};
与您的 std::vector<reference_wrapper>
类似,但没有额外的矢量。
views::indirect
Given a source range of readable values (e.g. pointers or iterators), return a new view that is the result of dereferencing each.
也可以用 view::transform
来完成。
我会通过索引公开 Foo
并提供获得迭代器的可能性
class Bar {
public:
class FooIt {
// Add typedefs for category etc
std::vector<std::shared_ptr<Foo>>::iterator it; // maybe template on this to easily provide the const overload too
public:
Foo& operator*() const {
return **it;
}
// write Functions to expose ++ etc of it
};
FooIt begin() {
return FooIt{begin(foos)};
}
FooIt end() {
retuen FooIt{end(foos)};
}
// Enables ranged for over Bar, only do if that makes sense for your Bar
Foo& getFoo(size_t index) { // maybe even operator [] if appropriate
return foos[index];
}
};
当然这是很多样板文件。但实际上,如果您在多个地方遇到此问题,您可以将 FooIt
编写为通用的模板版本。
我有一个包含共享指针向量的简单 class:
class Bar {
public:
/* stuff */
private:
std::vector<std::shared_ptr<Foo>> foos;
};
我希望通过 getFoos()
函数公开我的 foos
,该函数不会共享对象的所有权。一种方法是:
std::vector<std::reference_wrapper<Foo>> Bar::getFoos() const {
std::vector<std::reference_wrapper<Foo>> fooRefs;
fooRefs.reserve(foos.size());
for (auto& ptr : foos) {
fooRefs.push_back(std::ref(*ptr));
}
return fooRefs;
}
但这很丑陋。另外,我很可能需要缓存结果,因为这个函数经常被调用。更复杂,更丑陋。
是否有 cleaner/better 方法来处理这个问题?
可能是范围视图 range-v3:
class Bar {
public:
/* stuff */
auto get_foos() const { return foos | ranges::views::indirect; }
private:
std::vector<std::shared_pointer<Foo>> foos;
};
与您的 std::vector<reference_wrapper>
类似,但没有额外的矢量。
views::indirect
Given a source range of readable values (e.g. pointers or iterators), return a new view that is the result of dereferencing each.
也可以用 view::transform
来完成。
我会通过索引公开 Foo
并提供获得迭代器的可能性
class Bar {
public:
class FooIt {
// Add typedefs for category etc
std::vector<std::shared_ptr<Foo>>::iterator it; // maybe template on this to easily provide the const overload too
public:
Foo& operator*() const {
return **it;
}
// write Functions to expose ++ etc of it
};
FooIt begin() {
return FooIt{begin(foos)};
}
FooIt end() {
retuen FooIt{end(foos)};
}
// Enables ranged for over Bar, only do if that makes sense for your Bar
Foo& getFoo(size_t index) { // maybe even operator [] if appropriate
return foos[index];
}
};
当然这是很多样板文件。但实际上,如果您在多个地方遇到此问题,您可以将 FooIt
编写为通用的模板版本。