自动推导可以隐式添加常量吗?

Can auto deduction add implicitly constness?

考虑以下示例:

#include <iostream>
#include <string>

struct foo { std::string value; };
inline foo bar() { return { "42" }; }

std::string my_func() {
    auto &x = bar();
    ^^^^^^^^^^^^^^^^
    return x.value;
}

int main() {
  std::cout << my_func() << std::endl;  
}

编译它 GCC and CLANG 会发出同样的错误,很可能是正确的:

error: invalid initialization of non-const reference of type 'foo&' from an rvalue of type 'foo'

然而,令我惊讶的是它在 VC++2015 中编译并运行良好。

不,auto 不能添加常量。但是,MSVC++ 一直有一个扩展,非 const 左值引用可以绑定到右值。

我认为您可以使用 /Za 开关禁用此扩展程序。

Is this a bug of VC++2015?

该标准允许实现接受格式错误的代码作为扩展。然而,仍然需要实施才能发出诊断(这可能只是意味着 "emit a warning when certain flags are turned on")。

Does the standard dictates that auto can add implicitly constness to an object when a statement renders the program ill-formed?

不,标准要求 auto 推导使用与模板参数推导相同的规则(初始化列表除外)。如果T&不接受,那么auto&也不会。

Is this a bug of VC++2015?

Redmond 的被告经常称它为 "feature",但它是编译器混乱中的一个完全愚蠢的错误(可以用 /Za 修复)。让我们看看为什么...

auto &x = bar();

好的,所以你打电话给 bar(),不是吗?这会产生一个 rvalue,即没有地址的对象。现在,您无法将 lvalue(可以获取其地址的对象)引用 (a.k.a: &) 绑定到 rvalue。到目前为止,这就是您的代码非法的原因。

但是,C++ 语言中有一个特殊规则,允许 const lvalue 引用绑定到 rvalue,从而有效地延长其生命周期。所以,这将是有效的代码...

const auto &x = foo();

编辑:顺便说一句...

Does the standard dictates that auto can add implicitly constness to an object when a statement renders the program ill-formed?

用非标准语 terminology/plain 英语表达,如果 T& 被拒绝,auto& 也会被拒绝。 CV 限定符(constvolatile)是 而不是 auto.

自动推导出来的

我希望这对您有所启发!