How to make a "calculated attribute" for a C++ class using templates
I'm trying to implement generic method to put in a class a calculated value as a read-only memver value.
I've successfuly acomplished it using the following macro:
#define READONLY_PROPERTY(datatype, containerclass, access, name)\
class name ## _ ## datatype ## _ROP {\
public:\
name ## _ ## datatype ## _ROP(containerclass &c_): cclass(c_) {}\
operator datatype() const {return cclass.access();}\
private:\
containerclass &cclass;\
}name;\
friend class name ## _ ## datatype ## _ROP
that used in this class:
class TestClass {
public:
TestClass(): x(0), y(0), pixels(*this) {}
TestClass(int x_, int y_): x(x_), y(y_), pixels(*this) {}
int x;
int y;
READONLY_PROPERTY(int, TestClass, getPix, pixels);
private:
int getPix() {return x * y;}
};
generates the following working code (using g++):
class TestClass {
public:
TestClass(): x开发者_C百科(0), y(0), pixels(*this) {}
TestClass(int x_, int y_): x(x_), y(y_), pixels(*this) {}
int x;
int y;
class pixels_int_ROP {
public:
class pixels_int_ROP(TestClass &c_): cclass(C_) {}
operator int() const {return cclass.getPix();}
private:
TestClass &cclass;
} pixels;
friend class pixels_int_ROP;
private:
int getPix() {return x * y;}
};
The point is that I can then use the class this way:
TestClass tc(10,10);
std::cout << tc.pixels << std::endl;
Now I'm trying to do the same thing in a more C++ way using templates:
template<class T, class U, U (T::*F)()>;
class ReadOnlyProperty {
public:
ReadOnlyProperty(T const& instance): _instance(instance) {}
operator U const &() const {return _instance.*F();}
private:
T& _instance;
};
class TestClass {
public:
TestClass(): x(0), y(0), pixels(*this) {}
TestClass(int x_, int y_): x(x_), y(y_), pixels(*this) {}
int x;
int y;
ReadOnlyProperty<TestClass, int, &TestClass::getPix&> pixels;
private:
int getPix() {return x * y;}
};
but the compiler says:
error: incomplete type ‘TestClass’ used in nested name specifier
error: template argument 3 is invalid
in the line where the template class is instantiated.
Could you, please, help me?
Thanks in advance.
because getPix() was not declared when it is used as a template parameter, and _instance
have to be const
because ReadOnlyProperty constructor parameter is const
.
template< class T, class U, U (T::*F)() const >
class ReadOnlyProperty {
public:
ReadOnlyProperty(T const& instance): _instance(instance) {}
operator U const &() const {return (_instance.*F)();}
private:
const T& _instance;
};
class TestClass {
public:
TestClass(): x(0), y(0), pixels(*this) {}
TestClass(int x_, int y_): x(x_), y(y_), pixels(*this) {}
int x;
int y;
private:
int getPix() const {return x * y;}
public:
ReadOnlyProperty<TestClass, int, &TestClass::getPix> pixels;
};
Edit: Thanks to Georg Fritzsche, According to his comment, the last template parameter should take a const
member function and _instance.*F()
needs parentheses :) (oh! i forgot them!)
How about this:
#include <functional>
template<class R, class UA, class P>
class MyBind
{
public:
MyBind(UA unaryAction, P param)
:_unaryAction(unaryAction)
,_parameter(param)
{}
operator R const&() const
{
return _action(_parameter);
}
private:
UA _unaryAction;
P& _parameter;
};
Then it can be used like this:
class TestClass
{
typedef std::const_mem_fun_t<int, TestClass> MethodCall;
int getPix() const
{
return x * y;
}
public:
TestClass(int x_, int y_)
:x(x_)
,y(y_)
,pixels(std::mem_fun(&TestClass::getPix), *this)
{}
int x;
int y;
MyBind<int, MethodCall, TestClass> pixels;
};
精彩评论