member accessor template

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.
 
V

Vaclav Haisman

Kira Yamato wrote, On 17.2.2008 21:00:
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;
You must use &A::get_x if you want pointer to member function.
 
K

Kira Yamato

Kira Yamato wrote, On 17.2.2008 21:00:
You must use &A::get_x if you want pointer to member function.

Oh, thank you so much! It works now.

FYI, here's the correct template code:

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;
};

Example usage:

class A
{
public:
A() : x(*this) {}

int get_x() const;
void set_x(int);

member_accessor<A, int, &A::get_x, &A::set_x> x;
};

Now you can do

A a;
a.x = 3;
y = a.x;

Hmm... I wonder if it is possible to eliminate the template parameter C
from the template definition. Probably not.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,816
Latest member
SapanaCarpetStudio

Latest Threads

Top