c++ - 当 Type 为 unique_ptr 时,为 vector 添加 operator[]

标签 c++ templates c++11 sfinae

假设我们有下面的 vector 类,它已被缩短到最小值以展示问题。

template <typename T>
class VectorT : private std::vector<T>
{
  using vec = std::vector<T>;
public:
  using vec::operator[];
  using vec::push_back;
  using vec::at;
  using vec::emplace_back;

  // not sure if this is the beast way to check if my T is really a unique_ptr
  template<typename Q = T>
  typename Q::element_type* operator[](const size_t _Pos) const { return at(_Pos).get(); }
};

有什么方法可以检查 T 是否为 unique_ptr,如果是,则添加一个运算符 [] 以返回 unique_ptr::element_type*。同时,正常的 operator[] 也应该可以工作。

VectorT<std::unique_ptr<int>> uptr_v; 
uptr_v.emplace_back(make_unique<int>(1));
//int* p1 = uptr_v[0]; // works fine if using vec::operator[]; is commented out
                       // then of course it wont work for the normal case
//std::cout << *p1;

VectorT<int*> v;
v.emplace_back(uptr_v[0].get());
int *p2 = v[0];
std::cout << *p2;

有什么方法可以实现这样的目标吗?

已编辑:

我要求这个的原因是因为我可以说我的容器

class MyVec: public VectorT<std::unique_ptr<SomeClass>>

但我也可以拥有一个

class MyVecView: public VectorT<SomeClass*>

这两个类将具有几乎相同的功能。所以我试图通过做类似的事情来避免重复

template<typename T>
void doSomething(VectorT<T>& vec)
{
    SomeClass* tmp = nullptr;

    for (size_t i = 0; i < vec.size(); ++i)
    {
        tmp = vec[i]; // this has to work though
        ....
    }
}

那我当然可以

MyVec::doSomething(){doSomething(*this);}
MyVecView::doSomething(){doSomething(*this);}

这当然意味着 operator[] 必须适用于这两种情况

最佳答案

这里的目标是只有一个operator[]。具有多个 operator[] 的技术违反了 DRY(不要重复自己),并且很难避免有一个模板方法,如果实例化,其主体将无法编译(严格阅读标准,可能会导致您的代码格式不正确)。

所以我要做的是像这样模拟“将某些东西变成指针”:

namespace details {
  template<class T>
  struct plain_ptr_t;

  //specialzation for T*
  template<class T>
  struct plain_ptr_t<T*> {
    T* operator()(T* t)const{return t;}
  };

  //specialzation for std::unique_ptr
  template<class T, class D>
  struct plain_ptr_t<std::unique_ptr<T,D>> {
    T* operator()(std::unique_ptr<T>const& t)const{return t.get();}
  };

  //specialzation for std::shared_ptr
  template<class T>
  struct plain_ptr_t<std::shared_ptr<T>> {
    T* operator()(std::shared_ptr<T>const& t)const{return t.get();}
  };
}

struct plain_ptr {
  template<class T>
  typename std::result_of< details::plain_ptr_t<T>( T const& ) >::type
  operator()( T const& t ) const {
    return details::plain_ptr_t<T>{}( t );
  }
};

现在 plain_ptr 是一个仿函数,它将智能指针映射到普通指针,并将指针映射到指针。

它拒绝不是指针的东西。如果愿意,您可以将其更改为只让它们通过,但这需要一点小心。

然后我们使用它们来改进您的 operator[]:

typename std::result_of< plain_ptr(typename vec::value_type const&)>::type
operator[](size_t pos) const {
  return plain_ptr{}(at(pos));
}

注意它不再是一个模板

live example .

关于c++ - 当 Type 为 unique_ptr 时,为 vector 添加 operator[],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39784714/

相关文章:

c++ - 此语法的(可搜索的)名称是什么...?

c++ - Clion 中调试和运行模式之间奇怪的不同结果

c++ - 启用仅 header 库的优化以进行调试构建

c++ - ifstream 在 C++ 中的位置

c++ - boost 共享内存。当前有多少进程正在使用共享内存?

c++ - 工厂类实现问题

c++ - 如何使用 C++ 编写 vector vector 的通用打印

c++ - 如何在 C++ 中将外部类的模板类型用作内部类中的字段?

c++ - 如何将析构函数专门用于一种情况或某些情况?

当 push_back 新元素到 std::vector 时,C++ 引用发生变化