admin管理员组文章数量:1345906
I am trying to create a proxy template proxy class in C++
to manage transactions over a tree of nodes (INode
) forming my application data model.
Here is a very simple example:
Which I would like to access as trivially as possible:
rootNode->getA()->getX();
rootNode->getA()->setX(42.0f);
// NOT: rootNode->getA().edit()->setX(42.0f);
When a setter is called (e.g. setX
), a cache need to be created to manage the transaction mechanism, that is: getA()
in the first calls with getX()
returns a proxy pointing to nodeA
without creating a cache. But getA()
before setX
requires to generate that cache.
Here is a not-yet working proxy solution attempt:
/* Transaction wrapper template:
We attempt to have different behaviour, base on if the wrapper->getter()-const or wrapper->setter()
being getter and setter members of T
template <class T> */
class TransactionProxy {
public: using NonConstT = std::remove_cv_t < T > ;
// For const access
const T * operator -> () const {
std::cout << "Const operator-> called for " << typeid(T).name() << std::endl;
return m_obj;
}
// For non-const access
template < typename T_ = T,
std::enable_if_t < !std::is_const < T_ > ::value > * = nullptr >
T * operator -> () {
std::cout << "Non-const operator-> called for " << typeid(T).name() << std::endl;
return m_obj;
}
operator TransactionProxy < NonConstT > () const {
auto w = TransactionProxy < NonConstT > (const_cast < NonConstT * > (m_obj));
// INITIALIZATION of Transaction cache here!!
return w;
}
TransactionProxy(T * obj): m_obj(obj) {}
private: T * m_obj;
};
// ... dots
// Within RootNode
TransactionProxy <
const NodeA > getA() const {
return TransactionProxy <
const NodeA > (m_a.get());
}
This does not work, because the cast operator does not work implicitly.
You can find a full version of the code to experiment with here:
Code Full Version
The expected output is:
Example 1: Read-only operation
Const operator-> called for 8NodeRoot
Const operator-> called for 5NodeA
Getting X value: 1Example 2: Write operation
Const operator-> called for 8NodeRoot Initialize cache for 5NodeA
Non-const operator-> called for 5NodeA
Setting X from 1 to 42
Note: As you can see, only the last operator->()
before setX()
is Non-const and produce a transaction cache for the node NodeA
.
Is it possible to implement something like this without TS Reflexion? How?
Code Snippet:
#include <iostream>
#include <memory>
class INode {};
/* Transaction wrapper template:
We attempt to have different behaviour, base on if the wrapper->getter()-const or wrapper->setter()
being getter and setter members of T
template <class T> */
class TransactionProxy {
public: using NonConstT = std::remove_cv_t < T > ;
// For const access
const T * operator -> () const {
std::cout << "Const operator-> called for " << typeid(T).name() << std::endl;
return m_obj;
}
// For non-const access
template < typename T_ = T,
std::enable_if_t < !std::is_const < T_ > ::value > * = nullptr >
T * operator -> () {
std::cout << "Non-const operator-> called for " << typeid(T).name() << std::endl;
return m_obj;
}
operator TransactionProxy < NonConstT > () const {
auto w = TransactionProxy < NonConstT > (const_cast < NonConstT * > (m_obj));
// INITIALIZATION of Transaction cache here!!
return w;
}
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.0 f);
}
TransactionProxy <
const NodeA > getA() const {
return TransactionProxy <
const NodeA > (m_a.get());
}
};
int main() {
std::shared_ptr < NodeRoot > root = std::make_shared < NodeRoot > ();
// Example 1: Read-only operation (All access should be const)
std::cout << "Example 1: Read-only operation\n";
{
auto rootW = TransactionProxy <
const NodeRoot > (root.get());
[
[maybe_unused]
] float x = rootW -> getA() -> getX();
}
std::cout << std::endl;
// Example 2: Write operation (all access must be const, except the last before setX)
std::cout << "Example 2: Write operation\n";
{
auto rootW = TransactionProxy <
const NodeRoot > (root.get());
TransactionProxy < NodeA > (rootW -> getA()) -> setX(42.0 f);
// rootW->getA()->setX(42.0f); // NOT WORKING!!
// setX require a TransactionProxy<NodeA> (non-const)
// Looking for implicit const conversion, or const priority over non-const overloads
}
}
本文标签: Proxy Const to NonConst implicit transition in CStack Overflow
版权声明:本文标题:Proxy Const to Non-Const implicit transition in C++? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1743817474a2544183.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论