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/Lislong. For arithmetic operator, when binary operators have different types, the result produced will be of the common type; betweenintandlongit would belong.So
auto a = ir/L;, the type ofaislong. 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
Lisint, then forauto a = ir/L;, the type ofawill beint, then everything is fine.About the "the rvalue part of the error", when you pass a
longtofoo(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.longcould be implicitly converted toint, and temporary could be bound to lvalue reference to const, so passing alongvariable to bothbar(int x)andbar(const int&)is fine.BTW: When you write
int a = ir/L;, the result of typelongis implicitly converted toint. So you'll get anintthen it's fine to pass it tofoo(int&).