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.)
I have no positive evidence but I think it’s impossible. The following fails – for the same reason as your attempt – and I think that’s the furthest we can get:
Essentially, what this demonstrates is that the scope at which we want to declare our typedef simply has no access (be it direct or indirect) to
this
, and there’s no other (compiler independent) way of getting to the class’ type or name.I don't know all about these wacky templates, how about something super-simple:
Job done, unless you can't stand a couple of macros. You can even use
CLASSNAME
to declare your constructor(s) (and, of course, destructor).Live demo.
Building upon the answer by hvd, I found that the only thing that was missing was removing the reference, that is why the std::is_same check fails (b/c the resulting type is actually a reference to the type). Now this parameter-less macro can do all the work. Working example below (I use GCC 8.1.1).
Provide my version. The best thing is that its use is the same as the native class. However, it doesn't work for template classes.
Here's how you can do it without repeating the type of Foo:
If you want to derive from
Foo
then you should use the macroWITH_SELF_DERIVED
in the following way:You can even do multiple inheritance with as many base classes as you want (thanks to variadic templates and variadic macros):
I have verified this to work on gcc 4.8 and clang 3.4.
I also think it's impossible, here's another failed but IMHO interesting attempt which avoids the
this
-access:which fails because C++ requires you to qualify
self_f
with the class when you want to take it's address :(