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 recently discovered that
*this
is allowed in a brace-or-equal-initializer. Described in § 5.1.1 (from the n3337 working draft):With that in mind, the following code:
passes Daniel Frey's
static_assert
.Live example
this does not work on template types, as
self_check
is not called, so thestatic_assert
is not evaluated.We can do some hacks to make it work for
template
s as well, but it has a minor run time cost.an empty
struct
of size 1 byte is created in your class. If your type is instantiated,self
is tested against.You can use a macro instead of a regular class declaration, that will do that for you.
And then use like
#define END_CLASS };
would probably help readability.You could also take @Paranaix's
Self
and use it (it starts to get really hackish)I will repeat the obvious solution of "having to do it yourself". This is the succinct C++11 version of the code, which works with both simple classes and class templates:
You can see it in action at ideone. The genesis, leading to this result is below:
This has the obvious problem with copy-pasting the code to a different class and forgetting to change XYZ, like here:
My first approach was not very original - making a function, like this:
It is kind of lengthy, but please bear with me here. This has the advantage of working in C++03 without
decltype
, as the__self_check_helper
function is employed to deduce type ofthis
. Also, there is nostatic_assert
, but thesizeof()
trick is employed instead. You could make it much shorter for C++0x. Now this will not work for templates. Also, there is a minor issue with the macro not expecting semicolon at the end, if compiling with pedantic, it will complain about an extra unnecessary semicolon (or you will be left with an odd looking macro not ending in semicolon in the body ofXYZ
andABC
).Making a check on the
Type
that is passed toDECLARE_SELF
is not an option, as that would only check theXYZ
class (which is ok), oblivious toABC
(which has error). And then it hit me. A no-additional storage zero-cost solution that works with templates:This simply makes static assertion on a unique enum value (or at least unique in case you don't write all of your code on a single line), no type-comparing trickery is employed, and it works as static assert, even in templates. And as a bonus - the final semicolon is now required :).
I'd like to thank Yakk for giving me a good inspiration. I wouldn't write this without first seeing his answer.
Tested with VS 2008 and g++ 4.6.3. Indeed, with the
XYZ
andABC
example, it complains:Now if we make ABC a template:
We will get:
Only the line-number check triggered, as the function check was not compiled (as expected).
With C++0x (and without the evil underscores), you would need just:
I believe that the CStaticAssert bit is regrettably still required as it produces a type, which is typedef-ed in the template body (i suppose the same cannot be done with
static_assert
). The advantage of this approach is still its zero cost.What works in both GCC and clang is to create a typedef that refers to
this
by usingthis
in the trailing-return-type of a function typedef. Since this is not the declaration of a static member function, the use ofthis
is tolerated. You can then use that typedef to defineself
.Unfortunately, a strict reading of the standard says that even this is not valid. What clang does is check that
this
is not used in the definition of a static member function. And here, it indeed isn't. GCC doesn't mind ifthis
is used in a trailing-return-type regardless of the sort of function, it allows it even forstatic
member functions. However, what the standard actually requires is thatthis
is not used outside of the definition of a non-static member function (or non-static data member initialiser). Intel gets it right and rejects this.Given that:
this
is only allowed in non-static data member initialisers and non-static member functions ([expr.prim.general]p5),this
can be used ([over.call.func]p3),I think I can conclusively say that there is no way at all to implement
self
without including in some way, somewhere, the type name.Edit: There is a flaw in my earlier reasoning. "non-static member functions can only be called by unqualified name, even in unevaluated contexts, when this can be used ([over.call.func]p3)," is incorrect. What it actually says is
Inside a static member function,
this
may not appear, but it still exists.However, per the comments, inside a static member function, the transformation of
f()
to(*this).f()
would not be performed, and it that isn't performed, then [expr.call]p1 is violated:as there would be no member access. So even that wouldn't work.
A possible workaround (as you still have to write the type once):
For a more safer version we could assure that
T
actually derives fromSelf<T>
: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.