Properties of Properties as Templates
I try to implement C++ properties as templates as defined in WikiPedia
template <typename T> class property {
T value;
public:
T & operator = (const T &i) {
::std::cout << i << ::std::endl;
return value = i;
}
// This template class member function template serves the purpose to make
// typing more strict. Assignment to this is only possible with exact identical
// types.
template <typename T2> T2 & opera开发者_运维问答tor = (const T2 &i) {
::std::cout << "T2: " << i << ::std::endl;
T2 &guard = value;
throw guard; // Never reached.
}
operator T const & () const {
return value;
}
};
Now suppose I declare 2 classes, one of which contains the other as a property:
class A
{
public:
Property<double> pA1;
Property<double> pA2;
};
class B
{
public:
Property<A> pB1;
Property<double> pB2;
};
Now, is there a way to declare a B and access properties of A in it?
B b;
b.pB1.pA1=1;
does not work and;
((A) b.pB1).pA1=1;
works w/o error but does not actually change the actual A of B, because accesing ((A) b.pB1).pA1 gives unchanged value, since it probably makes a copy.
Is there a way to do it w/o pointers?
Casting one object to another type results in a temporary copy that goes out of scope as soon as that line of code is done. Did you mean to write ((A&) b.pB1).pA1=1;
?
b.pB1 doesn't have pA1 field. Instead, it has b.pB1.value.pA1. Using "." actually calls to "member access operator", bypassing type convert operator. Explicit type conversion works, but is not a safe code in a long term:
((A&)b.pB1).pA1 = 1.0;
A better way is to implement member access operator. It breaks encapsulation too (since the operator can be called explicitly), but much safer compared to explicit type conversion:
T* operator->() { return &value; }
...
b.pB1->pA1 = 3.0;
The full example:
#include <iostream>
using namespace std;
template <typename T>
class Property
{
T value;
public:
T& operator=(const T& x) {
return value = x;
}
template <typename T2>
T2 & operator = (const T2 &i) {
T2 &guard = value;
throw guard; // Never reached
}
operator T const & () const { return value; }
const T* operator->() const { return &value; }
T* operator->() { return &value; }
};
class A
{
public:
Property<double> pA1;
Property<double> pA2;
};
class B
{
public:
Property<A> pB1;
Property<double> pB2;
};
int
main()
{
B b;
//b.pB2 = 1; // not allowed by guard
b.pB2 = 1.0;
((A&)b.pB1).pA1 = 2.0;
cout << "b.pB1.pA1: " << ((A&)b.pB1).pA1 << endl;
b.pB1->pA1 = 3.0;
b.pB1->pA2 = 4.0;
cout << "b.pB1.pA1: " << b.pB1->pA1 << endl;
cout << "b.pB1.pA2: " << b.pB1->pA2 << endl;
return 0;
}
Have you tried adding a non-const function operator?
operator T& ()
{
return value;
}
This breaks encapsulation, but your sample usage suggests you want to be able to modify properties.
精彩评论