C++代理类Const到Non-Const隐式转换的实现方案问询
C++事务代理模板类实现方案(无需TS反射)
问题描述
我需要实现一个C++代理模板类TransactionProxy,用于管理基于INode节点的应用数据模型节点树事务,核心要求:
- 支持简洁链式访问语法:如
rootNode->getA()->getX()(只读)、rootNode->getA()->setX(42.0f)(写操作),无需额外调用edit() - 只读场景下,
getA()返回const代理,不创建事务缓存 - 写操作场景下,
getA()自动转换为非const代理,并触发事务缓存初始化
当前代码中的转换运算符无法完成隐式转换,导致rootW->getA()->setX(42.0f)无法正常执行,现寻求无需TS反射的可行实现方案。
修正后可运行代码
#include <iostream> #include <memory> #include <type_traits> class INode {}; template <class T> class TransactionProxy { public: using NonConstT = std::remove_cv_t<T>; // const访问的operator-> const T* operator->() const { std::cout << "Const operator-> called for " << typeid(T).name() << std::endl; return m_obj; } // 非const访问的operator->,仅当T非const时可用 template <typename T_ = T, std::enable_if_t<!std::is_const<T_>::value, int> = 0> T* operator->() { std::cout << "Non-const operator-> called for " << typeid(T).name() << std::endl; return m_obj; } // 从const代理隐式转换为非const代理,同时初始化事务缓存 operator TransactionProxy<NonConstT>() const { std::cout << "Initialize cache for " << typeid(NonConstT).name() << std::endl; return TransactionProxy<NonConstT>(const_cast<NonConstT*>(m_obj)); } TransactionProxy(T* obj) : m_obj(obj) {} private: T* m_obj; }; class NodeA : public INode { private: float m_x; public: NodeA(float x) : m_x(x) {} float getX() const { std::cout << "Getting X value: " << m_x << "\n"; return m_x; } void setX(float newX) { std::cout << "Setting X from " << m_x << " to " << newX << "\n"; m_x = newX; } }; class NodeRoot : public INode { private: std::shared_ptr<NodeA> m_a; public: NodeRoot() { m_a = std::make_shared<NodeA>(1.0f); } TransactionProxy<const NodeA> getA() const { return TransactionProxy<const NodeA>(m_a.get()); } }; int main() { std::shared_ptr<NodeRoot> root = std::make_shared<NodeRoot>(); // 示例1:只读操作(所有访问均为const) std::cout << "示例1:只读操作\n"; { auto rootW = TransactionProxy<const NodeRoot>(root.get()); [[maybe_unused]] float x = rootW->getA()->getX(); } std::cout << std::endl; // 示例2:写操作(除最后一步调用setX外,其余访问均为const) std::cout << "示例2:写操作\n"; { auto rootW = TransactionProxy<const NodeRoot>(root.get()); // 现在可直接调用,无需显式转换 rootW->getA()->setX(42.0f); } }
关键修改说明
- 补全模板定义:原代码漏写模板参数声明,将
TransactionProxy修正为真正的模板类,保证类型转换逻辑生效 - 完善隐式转换:在
TransactionProxy<const T>的转换运算符中添加事务缓存初始化逻辑,确保写操作触发缓存创建 - 优化重载逻辑:用SFINAE限制非
const版本operator->的生效条件,避免编译冲突,保证const/非const访问的优先级正确
期望输出
示例1:只读操作 Const operator-> called for 8NodeRoot Const operator-> called for 5NodeA Getting X value: 1 示例2:写操作 Const operator-> called for 8NodeRoot Initialize cache for 5NodeA Non-const operator-> called for 5NodeA Setting X from 1 to 42
内容的提问来源于stack exchange,提问作者Adrian Maire
相关产品推荐
相关产品推荐

