I must be misunderstanding how auto
c++11 and later resolves types. I have the following code:
void foo(int& x)
{
++x;
}
int main()
{
int i = 2;
int& ir = i;
long L = 5;
auto a = ir/L;
foo(a);
return 0;
}
This results in the compiler error:
test.cpp: In function 'int main()':
test.cpp:12:10: error: invalid initialization of non-const reference
of type ‘int&’ from an rvalue of type ‘int’
foo(a);
^
test.cpp:1:6: note: initializing argument 1 of ‘void foo(int&)’
void foo(int& x)
^~~
However, replacing auto
with int
(int a = ir/L;
) compiles fine and gives the expected result (a == 0
before the call to foo()
, and a == 1
after). After playing around with the code and seeing various error messages, I think auto
is deduced to long int&
. Defining the functions void bar(int x)
and void bar(const int& x)
results in the error message: call of overloaded ‘bar(long int&)’ is ambiguous
.
Correction from comments:
I don't understand how auto x = [int&]/[int]
result in an lvalue that can be passed by non-const ref while auto x = [int&]/[long]
results in an rvalue that cannot.
The result of
ir/L
islong
. For arithmetic operator, when binary operators have different types, the result produced will be of the common type; betweenint
andlong
it would belong
.So
auto a = ir/L;
, the type ofa
islong
. It can't be passed tofoo(int&)
because you can't bind lvalue reference to non-const with different type.On the other hand, given the type of
L
isint
, then forauto a = ir/L;
, the type ofa
will beint
, then everything is fine.About the "the rvalue part of the error", when you pass a
long
tofoo(int&)
, firstly the compiler will try to convert it toint
, which is a temporary (i.e. an rvalue) and can't be bound to lvalue reference to non-const.long
could be implicitly converted toint
, and temporary could be bound to lvalue reference to const, so passing along
variable to bothbar(int x)
andbar(const int&)
is fine.BTW: When you write
int a = ir/L;
, the result of typelong
is implicitly converted toint
. So you'll get anint
then it's fine to pass it tofoo(int&)
.