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.