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

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.


A possible workaround (as you still have to write the type once):

template<typename T>
struct Self
{
protected:
    typedef T self;
};

struct Foo : public Self<Foo>
{
    void test()
    {
        self obj;
    }
};

For a more safer version we could assure that T actually derives from Self<T>:

Self()
{
    static_assert(std::is_base_of<Self<T>, T>::value, "Wrong type passed to Self");
}

Notice that a static_assert inside a member function is probably the only way to check, as types passed tostd::is_base_of have to be complete.

Tags:

C++

C++11