Some problems with the implementation of properties based on a template in C ++

My goal was to make properties in C ++, as in C #, with a non-trivial set of / get behavior. Here, the property object contains refs for controlling prop and its set / get methods.

Implementation, the contents of Property.h:

#include <iostream> using namespace std; namespace First { template <class Master, class Type> struct Property { Master &master; const Type (Master::*&get) () const; Type (Master::*&set)(Type value); Property ( Master &master, const Type (Master::*get) () const, Type (Master::*set)(Type value) ): get(get), set(set), master(master) { } operator const Type() const { cout << "inside" << endl; return (master.*get)(); } Type operator = (Type value) { return (master.*set)(value); } }; // Test chamber. class R { float x; const float getx() const { cout << "returning " << 0 << endl; return 0; } float setx(float value) { cout << "setting " << value << " in place of " << x << endl; return x = value; } public: Property<R, float> X; R(): X(*this, &R::getx, &R::setx) { } }; } 

I also created a .cpp file:

 #include "Property.h" using namespace First; int main() { R r; rX = 10; float y = rX; } 

The program takes the "assignment" step, prints "0 - 10", but segfaults on the call to "extract", it does not matter which code (or not at all) inside "R :: getx ()".

 ~/Sources$ ./a.out setting 10 in place of 0 inside zsh: segmentation fault ./a.out 

It seems that calling (master. * Get ()) by itself causes a failure. What is wrong with this code?

UPD: it is checked that any other call of master functions leads to segfault, only one call (master. * Set). This call seems to invalidate the state of the object, member-to-pr, property itself or phase of the moon.

+4
source share
1 answer
 const Type (Master::*&get) () const; Type (Master::*&set)(Type value); 

Remove & from the above definitions. Due to & each of them is associated with constructor parameters that do not exist after the constructor returns.

Also note that (master.*set)(value) seems to work because you're out of luck. In fact, it causes undefined behavior. But you are lucky that you will soon find out the problem when (master.*get)() fails by providing segfault.

Using:

 const Type (Master::*get) () const; Type (Master::*set)(Type value); 

Now it should work without any problems, since this will lead to copying the addresses in the initialization list, and not to the parameters!

+6
source

All Articles