C++11 从 int& 和 long 的算术运算中自动推导类型

C++11 auto type deduction from arithmetic operation on int& and long

我一定是误解了 auto c++11 及更高版本如何解析类型。我有以下代码:

void foo(int& x)
{
    ++x;
}

int main()
{
    int i = 2;
    int& ir = i;
    long L = 5;
    auto a = ir/L;
    foo(a);

    return 0;
}

这导致编译器错误:

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)
      ^~~

但是,将 auto 替换为 int (int a = ir/L;) 可以很好地编译并给出预期的结果(a == 0 在调用 foo() 之前,并且a == 1 之后)。在玩弄代码并看到各种错误消息后,我认为 auto 被推断为 long int&。定义函数 void bar(int x)void bar(const int& x) 会导致错误消息:call of overloaded ‘bar(long int&)’ is ambiguous.

根据评论更正:

我不明白 auto x = [int&]/[int] 如何导致左值可以通过非常量引用传递,而 auto x = [int&]/[long] 导致右值不能。

ir/L的结果是long。对于arithmetic operator,当二元运算符有不同的类型时,产生的结果将是共同的类型;在 intlong 之间它将是 long.

所以auto a = ir/L;a的类型是long。它不能传递给 foo(int&) 因为你不能将左值引用绑定到不同类型的非常量。

另一方面,给定 L 的类型是 int,那么对于 auto a = ir/L;a 的类型将是 int,那么一切都很好。

关于"the rvalue part of the error",当你将long传递给foo(int&)时,编译器首先会尝试将其转换为int,这是一个临时的(即一个右值)并且不能绑定到对非常量的左值引用。

long 可以隐式转换为 int,临时可以绑定到对 const 的左值引用,因此将 long 变量传递给 bar(int x)bar(const int&) 没问题。

顺便说一句:当你写 int a = ir/L; 时,类型 long 的结果被隐式转换为 int。所以你会得到一个 int 然后把它传递给 foo(int&).

就可以了

您使用过 auto 的事实无关紧要。

along 类型,因为参数提升的规则。

因为 foo 通过引用获取参数 ,编译失败,因为 int& 无法绑定到 long 类型(即使它们大小相同,补码表示相同)。