K
Kira Yamato
Ok, I'm trying to do something funky here, just to see how much the C++
syntax can be stretched. Here's the problem I was trying to solve.
Suppose you have the following common situation of a class A with two
accessor methods for x:
class A
{
public:
int get_x() const;
void set_x(int);
};
Normally, we would have the following syntax:
// (1)
A a;
a.set_x(3);
int y = a.get_x();
However, let's say I want to implement the following syntax instead
// (2)
A a;
a.x = 3;
int y = a.x;
But I want (2) to expand out to (1) at compile time so that I keep the
efficiency also.
So, my attempt to try this involved first writing the following template:
template<typename C, typename M, M (C::*get)() const, void
(C::*set)(const M &)>
class member_accessor : private boost::noncopyable
{
public:
member_accessor(C &c) : c(c) {}
operator M() const { return c.*get(); }
member_accessor &operator=(const M &n) { c.*set(n); return *this; }
private:
C &c;
};
With this template I can support the syntax in (2) with the new class A as:
class A
{
public:
int get_x() const;
void set_x(int);
member_accessor<A, int, get_x, set_x> x;
};
Nice, isn't it? Except that g++4.0.1 doesn't compile it. Grrr....
The error message I got was this:
a.cpp:27: error: 'int A::get_x() const' cannot appear in a constant-expression
a.cpp:27: error: 'void A::set_x(int)' cannot appear in a constant-expression
a.cpp:27: error: template argument 3 is invalid
a.cpp:27: error: template argument 4 is invalid
So, now I humbly seek some help here from the newsgroup. How can I get
this to work? Can this even be made to work? And work in a
re-useable, efficient and clean way?
Thanks.
syntax can be stretched. Here's the problem I was trying to solve.
Suppose you have the following common situation of a class A with two
accessor methods for x:
class A
{
public:
int get_x() const;
void set_x(int);
};
Normally, we would have the following syntax:
// (1)
A a;
a.set_x(3);
int y = a.get_x();
However, let's say I want to implement the following syntax instead
// (2)
A a;
a.x = 3;
int y = a.x;
But I want (2) to expand out to (1) at compile time so that I keep the
efficiency also.
So, my attempt to try this involved first writing the following template:
template<typename C, typename M, M (C::*get)() const, void
(C::*set)(const M &)>
class member_accessor : private boost::noncopyable
{
public:
member_accessor(C &c) : c(c) {}
operator M() const { return c.*get(); }
member_accessor &operator=(const M &n) { c.*set(n); return *this; }
private:
C &c;
};
With this template I can support the syntax in (2) with the new class A as:
class A
{
public:
int get_x() const;
void set_x(int);
member_accessor<A, int, get_x, set_x> x;
};
Nice, isn't it? Except that g++4.0.1 doesn't compile it. Grrr....
The error message I got was this:
a.cpp:27: error: 'int A::get_x() const' cannot appear in a constant-expression
a.cpp:27: error: 'void A::set_x(int)' cannot appear in a constant-expression
a.cpp:27: error: template argument 3 is invalid
a.cpp:27: error: template argument 4 is invalid
So, now I humbly seek some help here from the newsgroup. How can I get
this to work? Can this even be made to work? And work in a
re-useable, efficient and clean way?
Thanks.