[英]Turning vector of shared_ptr into vector of shared_ptr to const
Let 让
class A
{
std::vector<std::shared_ptr<int>> v_;
};
Now I'd like to add access to v_
using two public member functions 现在我想使用两个公共成员函数添加对v_
访问
std::vector<std::shared_ptr<int>> const & v() { return v_; }
and 和
std::vector<std::shared_ptr<int const> const & v() const { TODO }
I cannot replace TODO
with return v_;
我不能用return v_;
替换TODO
return v_;
though. 虽然。
One option would be to not return a reference but a copy. 一种选择是不返回引用而是复制。 Apart from the obvious performance penalty, this would also make the interface somewhat less desirable. 除了明显的性能损失之外,这也会使界面不那么令人满意。
Another option is to make TODO
equal to return reinterpret_cast<std::vector<std::shared_ptr<int const>> const &>(v_);
另一种选择是使TODO
等于return reinterpret_cast<std::vector<std::shared_ptr<int const>> const &>(v_);
My question is, is this undefined behavior? 我的问题是,这是不确定的行为吗? Or, alternatively, is there a better option, preferably without using reinterpret_cast
? 或者,是否有更好的选择,最好不使用reinterpret_cast
?
A way to avoid copying the container is to provide transform iterators that transform the element on dereference: 避免复制容器的一种方法是提供转换迭代器,在迭代引用时转换元素:
#include <vector>
#include <memory>
#include <boost/iterator/transform_iterator.hpp>
class A
{
std::vector<std::shared_ptr<int> > v_;
struct Transform
{
template<class T>
std::shared_ptr<T const> operator()(std::shared_ptr<T> const& p) const {
return p;
}
};
public:
A() : v_{std::make_shared<int>(1), std::make_shared<int>(2)} {}
using Iterator = boost::transform_iterator<Transform, std::vector<std::shared_ptr<int> >::const_iterator>;
Iterator begin() const { return Iterator{v_.begin()}; }
Iterator end() const { return Iterator{v_.end()}; }
};
int main() {
A a;
// Range access.
for(auto const& x : a)
std::cout << *x << '\n';
// Indexed access.
auto iterator_to_second_element = a.begin() + 1;
std::cout << **iterator_to_second_element << '\n';
}
Putting aside the discussion of whether or not you should return a reference to a member... 暂且讨论你是否应该返回对成员的引用......
std::vector
already propagates its own const
qualifier to the references, pointee's and iterators it returns. std::vector
已经将自己的const
限定符传播给它返回的引用,指针和迭代器。 The only hurdle is making it propagate further to the pointee type of the std::shared_ptr
. 唯一的障碍是让它进一步传播到std::shared_ptr
的指针类型。 You can use a class like std::experimental::propagate_const
(that will hopefully be standardized) to facilitate that. 你可以使用像std::experimental::propagate_const
这样的类(希望能够标准化)来促进这一点。 It will do as its name implies, for any pointer or pointer-like object it wraps. 它就像它的名字所暗示的那样,对于它包装的任何指针或指针式对象。
class A
{
using ptr_type = std::experimental::propagate_const<std::shared_ptr<int>>;
std::vector<ptr_type> v_;
};
Thus TODO
can become return v_;
因此TODO
可以成为return v_;
, and any access to the pointees (like in the range-based for you wish to support) will preserve const-ness. ,任何对指定者的访问(如在你希望支持的范围内)都将保持一致性。
Only caveat is that it's a moveable only type, so copying out an element of the vector will require a bit more work (for instance, by calling std::experimental::get_underlying
) with the element type of the vector itself. 唯一需要注意的是它只是一个可移动的类型,因此复制一个向量元素需要更多的工作(例如,通过调用std::experimental::get_underlying
)和向量本身的元素类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.