我想有一个包装类,它保存并返回一个指向包装容器的某个元素的指针。它看起来像:
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
}
答案 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::string
和std::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