I want a function return its real type, even it called in subclass. Here is the test code:
class Super
{
public:
Super(){};
virtual auto getSelf() -> decltype(*this)&
{
return *this;
}
void testSuper(){};
};
class Sub : public Super
{
public:
void testSub(){};
};
int main()
{
Sub().getSelf().testSuper();//OK
//Sub().getSelf().testSub();//Error
return 0;
}
In Objective-C, I can use instanttype to solve this.
But in C++, is it possible?
By the way, I do not want a template implementation, since it may increase the code size.
But in C++, is it possible?
Yes, and just like anything in C++, there is many ways to do it. But both ways require you to add something in the Sub class.
If you don't need virtual functions, then simply override (statically) that function:
struct Super {
auto getSelf() -> Super& {
return *this;
}
void testSuper(){};
};
struct Sub : Super {
auto getSelf() -> Sub& {
return *this;
}
void testSub(){};
};
int main() {
Sub().getSelf().testSuper(); //OK
Sub().getSelf().testSub(); //OK too!
return 0;
}
Of course, if you don't like copy pasting that code, you can always create a mixin class (a CRTP template):
template<typename Subclass>
struct AddGetSelf {
auto getSelf() -> Subclass& {
return static_cast<Subclass&>(*this);
}
};
You can the use that mixin in your classes like this:
struct Super : AddGetSelf<Super> {
using AddGetSelf<Super>::getSelf;
void testSuper(){};
};
struct Sub : Super, AddGetSelf<Sub> {
using AddGetSelf<Sub>::getSelf;
void testSub(){};
};
If you need virtual polymorphism, you can rely on covariant return types:
struct Super {
virtual auto getSelf() -> Super& {
return *this;
}
void testSuper(){};
};
struct Sub : Super {
auto getSelf() -> Sub& override {
return *this;
}
void testSub(){};
};
int main() {
Sub().getSelf().testSuper(); //OK
Sub().getSelf().testSub(); //OK too!
return 0;
}
Here's a live example at Coliru
If you are worried about binary size, consider static linking and link time optimisation.
I suggest you to try out both solutions and compare binary sizes, since template size increase can be cancelled out by compiler optimisation, and virtual polymorphism can prevent the compiler to do these optimisations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With