繁体   English   中英

将shared_ptr的向量转换为shared_ptr的向量为const

[英]Turning vector of shared_ptr into vector of shared_ptr to const

class A
{
    std::vector<std::shared_ptr<int>> v_;
};

现在我想使用两个公共成员函数添加对v_访问

std::vector<std::shared_ptr<int>> const & v() { return v_; }

std::vector<std::shared_ptr<int const> const & v() const { TODO }

我不能用return v_;替换TODO return v_; 虽然。

一种选择是不返回引用而是复制。 除了明显的性能损失之外,这也会使界面不那么令人满意。

另一种选择是使TODO等于return reinterpret_cast<std::vector<std::shared_ptr<int const>> const &>(v_);

我的问题是,这是不确定的行为吗? 或者,是否有更好的选择,最好不使用reinterpret_cast

避免复制容器的一种方法是提供转换迭代器,在迭代引用时转换元素:

#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';
}

暂且讨论你是否应该返回对成员的引用......

std::vector已经将自己的const限定符传播给它返回的引用,指针和迭代器。 唯一的障碍是让它进一步传播到std::shared_ptr的指针类型。 你可以使用像std::experimental::propagate_const这样的类(希望能够标准化)来促进这一点。 它就像它的名字所暗示的那样,对于它包装的任何指针或指针式对象。

class A
{
    using ptr_type = std::experimental::propagate_const<std::shared_ptr<int>>;
    std::vector<ptr_type> v_;
};

因此TODO可以成为return v_; ,任何对指定者的访问(如在你希望支持的范围内)都将保持一致性。

唯一需要注意的是它只是一个可移动的类型,因此复制一个向量元素需要更多的工作(例如,通过调用std::experimental::get_underlying )和向量本身的元素类型。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM