I came up with the following piece of code thinking that it wouldn't work, but surprisingly to me it works absolutely fine, and I would like some explanation.
#include <cstdio>
#include <algorithm>
struct Abstract
{
Abstract()
{ printf("\tConstructing Abstract instance.\n"); }
virtual const char* name() const =0;
auto talk() const -> decltype(*this)
{
printf("My name is %s.\n",name());
return *this;
}
};
struct Concrete
: public Abstract
{
Concrete()
{ printf("\tConstructing Concrete instance.\n"); }
const char* name() const
{ return "Bond"; }
};
int main()
{
Concrete C;
printf("James %s.\n",C.talk().name());
}
The output of this code is:
Constructing Abstract instance.
Constructing Concrete instance.
My name is Bond.
James Bond.
Q1 (This is non-specific to C++11, just remove decltype
and replace auto
by const Abstract&
). Why does the compiler accept the syntax C.talk().name()
?
Unless I am mistaken, I think the expression C.talk()
could either be a prvalue (copy of Abstract, not the case because there is only one constructor output) or an lvalue reference, in which case I am not sure to what because an lvalue reference to an abstract class seems impossible to me too.
Q2 This leads me to the second question: how does decltype
"know" to return some kind of reference, and not a plain value?