For some syntactic sugar I want to return a reference to this, but when inherited, the function should return the type of the child class:
class base {
T &operator!() { return *this; }
};
base b; b = !b;
class child : public base {};
child c; c = !c;
Because of the operator, I can’t just return the pointer and dynamic_cast it, it has to be a reference.
Is that even possible? Using decltype(*this) for T doesn’t work, neither does auto f()->decltype(*this), because of this (although I don’t understand why, in the auto-case)
In Scala you can write something like:
template<typename T> class base {
T &f() { return *this; }
};
class child : public base<child> {};
But my g++ won’t accept this (not sure if that’s bug or just not in the spec?)
Of course there’s the explicit way, but I wonder if this can be avoided using C++11 features?
class child : public base {
child &operator!() { base::operator!(); return *this }
};
You can use the CRTP to do this if you’re allowed to make
basea template:Note the extra cast here. The reason this works is that if you have a class like this one:
Then if you call
refToThisfrom inside that class, it will call the base class version. Since the class inherits fromBase<Subclass>, the instantiated template forrefToThiswill beThis code is safe, because the
thispointer does indeed point to aSubclassobject. Moreover, thestatic_castwill ensure that the cast fails at compile-time if the derived class doesn’t inherit fromBaseproperly, as the pointer type won’t be convertible.The reason that the cast is necessary here is that if you just say
Then there is a type error in the program, since a
Baseby itself is not aDerived, and if you could convert aBase&into aDerived&without any checks you could break the type system.That said… I wouldn’t do this at all. Overloading
operator!for this purpose makes the code less readable, and just writing*thisis so idiomatic that hiding it will make your code much harder to understand. Using all of this template machinery to avoid something that’s common C++ seems misguided. If you’re doing something else before returning the reference that’s fine, but this just doesn’t seem like a good idea.Hope this helps!