为何无法将std::experimental::propagate_const用于数组?
为什么
std::experimental::propagate_const不能用于数组版std::unique_ptr? 报错原因
你遇到的编译错误根源很直接:std::experimental::propagate_const的内部实现依赖被包装的指针类型提供operator*(解引用运算符),但数组特化的std::unique_ptr<T[]>并没有定义这个运算符。
从报错信息能看到,propagate_const在推导类型时尝试执行*std::declval<_Tp&>(),也就是对std::unique_ptr<int[]>调用解引用,但标准库为数组版unique_ptr只提供了operator[]用于访问元素——直接解引用数组指针本身无意义(数组不是单个对象),所以标准没有给它实现operator*,最终导致模板实例化失败。
满足需求的替代方案
你的核心需求是:在类的const成员函数中,禁止通过动态数组指针修改数组元素。既然propagate_const不支持数组版unique_ptr,我们可以手动实现一个简易的const传播包装器,专门适配数组指针:
自定义数组指针的const传播包装器
#include <memory> template <typename ArrayPtr> class propagate_const_array { private: ArrayPtr m_ptr; using elem_type = typename ArrayPtr::element_type; public: // 转发构造函数,兼容make_unique的返回值 propagate_const_array(ArrayPtr ptr) : m_ptr(std::move(ptr)) {} // 非const成员函数:返回可修改的元素引用 elem_type& operator[](std::size_t idx) { return m_ptr[idx]; } // const成员函数:返回不可修改的const元素引用 const elem_type& operator[](std::size_t idx) const { return m_ptr[idx]; } // 提供get()方法,区分const/非const语义 elem_type* get() { return m_ptr.get(); } const elem_type* get() const { return m_ptr.get(); } // 默认支持移动语义 propagate_const_array(propagate_const_array&&) = default; propagate_const_array& operator=(propagate_const_array&&) = default; // 禁用拷贝(跟随unique_ptr的语义) propagate_const_array(const propagate_const_array&) = delete; propagate_const_array& operator=(const propagate_const_array&) = delete; };
使用示例
把原来的propagate_const<std::unique_ptr<int[]>>替换成这个自定义包装器,就能在const成员函数中阻止修改数组元素:
struct A { void foo() const { a[0] = 2; // 编译报错:无法给const引用赋值,符合预期 } propagate_const_array<std::unique_ptr<int[]>> a = std::make_unique<int[]>(2); };
简化替代方案
如果场景允许,也可以直接用std::vector<int>代替unique_ptr<int[]>:vector在const成员函数中会自动变成const容器,operator[]返回const引用,天然就能阻止修改,不需要额外包装:
struct A { void foo() const { a[0] = 2; // 编译报错 } std::vector<int> a; A() : a(2) {} // 初始化2个元素 };
内容的提问来源于stack exchange,提问作者wimalopaan
相关产品推荐
相关产品推荐

