采用const和非const类型的C ++模板类

时间:2017-02-26 06:49:05

标签: c++ templates const

我想有一个包装类,它保存并返回一个指向包装容器的某个元素的指针。它看起来像:

template <typename T>
class VectorWrapper
{
public:
  VectorWrapper(vector<T>& container) {
    m_pointer = &container[0];
  }

  T* GetPointer() { return m_pointer; }

private:
  T* m_pointer;
};

问题是输入容器有时可能是const类型。在这种情况下,是否有一种优雅的方法可以避免VectorWrapper的另一种实现,而是返回const T*

我的方法(没有运气)如下:

template <typename T>
VectorWrapper<T> make_vector_wrapper(vector<T>& container) {
  return VectorWrapper<T>(container);
}

template <typename T>
VectorWrapper<T> make_vector_wrapper(const vector<T>& container) {
  // I'm stuck here. return VectorWrapper<const T>(container); doesn't work.
}

void Foo(const vector<int>& const_container) {
  vector<int> mutable_container(10);

  auto v1 = make_vector_wrapper(mutable_container);
  *(v1.GetPointer()) = 1;     // Ok

  auto v2 = make_vector_wrapper(const_container);
  int x = *(v2.GetPointer()); // Ok
  *(v2.GetPointer()) = 1;     // Would like compile error
}

1 个答案:

答案 0 :(得分:3)

您可以在容器上模板而不是元素,因为它是const的容器。这是一个快速模型(如果向量重新定位,它不起作用):

#include <iostream>
#include <vector>

template <typename T>
class VectorWrapper
{
    using value_type = std::remove_reference_t<decltype(((T*)nullptr)->at(0))>;

public:
  VectorWrapper(T& container) {
    m_pointer = &container[0];
  }

  value_type* GetPointer() { return m_pointer; }

private:
  value_type* m_pointer;
};

template <typename T>
VectorWrapper<T> make_vector_wrapper(T& container) {
  return VectorWrapper<T>(container);
}

int main() {
  std::vector<int> mutable_vector(10);
  auto v1 = make_vector_wrapper(mutable_vector);
  *(v1.GetPointer()) = 1;     // Ok

  const std::vector<int> const_vector(10);
  auto v2 = make_vector_wrapper(const_vector);
//  *(v2.GetPointer()) = 1;     // error
}

修改

这是一个更简单的解决方案(auto返回类型的C ++ 14),它还处理基础矢量数据的重定位。

template <typename T>
class VectorWrapper
{
  T& m_container;
public:
  VectorWrapper(T& container) : m_container(container) {}

  auto GetPointer() { return m_container.data(); }
};

<强>更新

它也适用于其他容器类,例如std::stringstd::array

  std::string mutable_string;
  auto s1 = make_vector_wrapper(mutable_string);
//  *(s1.GetPointer()) = 1;     // error, sd::string::data returns char const *

  std::array<int, 4> mutable_array;
  auto a1 = make_vector_wrapper(mutable_array);
  *(a1.GetPointer()) = 1;     // Ok

  const std::array<int, 4> const_array = {1,2,3,4};
  auto a2 = make_vector_wrapper(const_array);
//  *(a2.GetPointer()) = 1;     // error