Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I implement an autonomous `self` member type in C++?

Tags:

c++

c++11

C++ lacks the equivalent of PHP's self keyword, which evaluates to the type of the enclosing class.

It's easy enough to fake it on a per-class basis:

struct Foo {    typedef Foo self; }; 

but I had to write Foo again. Maybe I'll get this wrong one day and cause a silent bug.

Can I use some combination of decltype and friends to make this work "autonomously"? I tried the following already but this is not valid in that place:

struct Foo {    typedef decltype(*this) self; };  // main.cpp:3:22: error: invalid use of 'this' at top level //     typedef decltype(*this) self; 

(I'm not going to worry about the equivalent of static, which does the same but with late binding.)

like image 942
Lightness Races in Orbit Avatar asked Jan 15 '14 17:01

Lightness Races in Orbit


1 Answers

Here's how you can do it without repeating the type of Foo:

template <typename...Ts> class Self;  template <typename X, typename...Ts> class Self<X,Ts...> : public Ts... { protected:     typedef X self; };  #define WITH_SELF(X) X : public Self<X> #define WITH_SELF_DERIVED(X,...) X : public Self<X,__VA_ARGS__>  class WITH_SELF(Foo) {     void test()     {         self foo;     } }; 

If you want to derive from Foo then you should use the macro WITH_SELF_DERIVED in the following way:

class WITH_SELF_DERIVED(Bar,Foo) {     /* ... */ }; 

You can even do multiple inheritance with as many base classes as you want (thanks to variadic templates and variadic macros):

class WITH_SELF(Foo2) {     /* ... */ };  class WITH_SELF_DERIVED(Bar2,Foo,Foo2) {     /* ... */ }; 

I have verified this to work on gcc 4.8 and clang 3.4.

like image 148
Ralph Tandetzky Avatar answered Oct 06 '22 01:10

Ralph Tandetzky