boost::shared_ptr<std::vector<something>> 运算符[]的用法

boost::shared_ptr<std::vector<something>> usage of operator[]

我有一个看起来像这样的结构。

typedef struct superCellBoxStruct {
    float_tt cmx,cmy,cmz;  /* fractional center of mass coordinates */
    float_tt ax,by,cz;
    boost::shared_ptr<std::vector<atom>> atoms; /* contains all the atoms within the super cell */
} superCellBox;

现在,当我想访问 atoms[i] 时,我得到了

error: invalid use of ‘boost::detail::sp_array_access >::type {aka void}’

在我的应用程序中传递共享向量的正确方法是什么,或者访问它的 operator[] 的正确方法是什么?

选一个:

(*atoms)[i]    
atoms->operator[](i);

我通常选择第一个,但它们都是等价的。

附带说明一下,根据我的经验,这样的 shared_ptr<vector> 通常是糟糕设计的征兆,也许您想将整个 superCellBox 放在 shared_ptr 中?

此外,这不是 C,请使用 struct name {}; 代替 typedef struct tagName {} name;

如果可以,请选择 unique_ptr<T[]>,因为您可以免费获得 operator[] (§ 20.7.1.3.3):

快速演示:

Live On Coliru

#include <memory>
#include <iostream>

int main() {
    std::unique_ptr<int[]> p(new int[3] { 1,2,3 });

    std::cout << "Before: " << p[0] << ", " << p[1] << ", " << p[2] << ";\n";
    p[1] = 42;
    std::cout << "After:  " << p[0] << ", " << p[1] << ", " << p[2] << ";\n";
}

打印:

Before: 1, 2, 3;
After:  1, 42, 3;

更新

针对评论,做个小包装就可以了:

Live On Coliru

#include <memory>

template <typename RAContainer> struct shared_randomaccess_container
{
    template <typename... A> shared_randomaccess_container(A&&... args) 
        : _ptr(new RAContainer{ std::forward<A>(args)... })
    { }
    template <typename T> shared_randomaccess_container(std::initializer_list<T> init)
        : _ptr(std::make_shared<RAContainer>(init))
    { }

    auto begin() const -> typename RAContainer::const_iterator { return _ptr->begin(); }
    auto end  () const -> typename RAContainer::const_iterator { return _ptr->end  (); }
    auto begin()       -> typename RAContainer::iterator       { return _ptr->begin(); }
    auto end  ()       -> typename RAContainer::iterator       { return _ptr->end  (); }

    template <typename Idx>
    typename RAContainer::value_type const& operator[](Idx i) const { return (*_ptr)[i]; }
    template <typename Idx>
    typename RAContainer::value_type& operator[](Idx i) { return (*_ptr)[i]; }

    template <typename Idx>
    typename RAContainer::value_type const& at(Idx i) const { return _ptr->at(i); }
    template <typename Idx>
    typename RAContainer::value_type& at(Idx i) { return _ptr->at(i); }

  protected:
    using Ptr = std::shared_ptr<RAContainer>;
    Ptr _ptr;
};

////////////////////////////////////////////////////
// demo intances
#include <vector>

template <typename... Ts> using shared_vector = shared_randomaccess_container<std::vector<Ts...> >;

您可以像这样使用它:

shared_vector<int> sv {1,2,3};

std::cout << "Before: ";
for (auto i : sv) std::cout << i << " ";

sv[1] = 42;
std::cout << "\nAfter:  ";
for (auto i : sv) std::cout << i << " ";

打印:

Before: 1 2 3 
After:  1 42 3 

奖金

让我们也支持使用相同技术的聚合初始化容器

Live On Coliru

输出:

void test() [with With = std::vector<int>]
Before: 1 2 3 
After:  1 42 3 

void test() [with With = std::array<int, 3ul>]
Before: 1 2 3 
After:  1 42 3 

void test() [with With = shared_randomaccess_container<std::vector<int>, false>]
Before: 1 2 3 
After:  1 42 3 

void test() [with With = shared_randomaccess_container<std::array<int, 3ul>, true>]
Before: 1 2 3 
After:  1 42 3