I need the following code to work:
class Parent{
public:
virtual void fun(){throw 0};
};
class Child:public Parent{
public:
virtual void fun(){/*Success*/};
};
Parent& getChild(){
return *(new Child());
}
void main(){
auto child=getChild();
child.fun();
}
But for some reason auto
creates a Parent
instead of Parent &
which would correctly use the derived method. Is there a way to force auto
to create a reference instead of using a simple Instance?
The C++ standard explains that auto is deducted from the initilizer value:
Declarations
[dcl.spec.auto]/1:
Theauto
anddecltype(auto)
type-specifiers are used to designate a placeholder type that will be replaced later by deduction from an initializer.Initializers
[dcl.init]/1:
A declarator can specify an initial value for the identifier being declared.
So when you write the following declarators:
int t = f(10);
auto x = y;
auto child = getChild();
the right side is evaluated as an expression that yields a value. And this value is used to initialize the variable declared on the left side.
A value is not a reference. It's not like pointers and adresses. In an expression evaluation, whenever a reference is used, it's the referred value that is taken into consideration. You can see this with the following simple snippet:
int x=15;
int&y = x;
cout << x <<", " << y <<", " << &x<<endl;
cout << typeid(x).name() <<", " << typeid(y).name() <<", " << typeid(&x).name() <<endl;
In your case, the expression value is therefore a Parent
and not Parent &
. This is why your auto
will be deduced to have the Parent
type.
The C++ standard does however not consider all the values in the same manner. In [basic.lval]
it makes an important distinction between different kind of values, which can be lvalues, xvalues and prvalues. In your case getChild()
evaluates to an lvalue that is the object to which you referred and not some temporary copy of it.
When you have such an lvalue, you can create a reference to it:
[dcl.ref]
/2: A reference type that is declared using&
is called an lvalue reference, (...)
But you need to do this explicitly by saying that your auto should be a reference:
auto &child = getChild();
Edit: More infos on the way auto works: Herb Sutter's GotW blog