在模板中强制转换为引用似乎会抛弃恒定性

Casting to reference in a template seems to cast away const-ness

本文关键字:引用 恒定性 抛弃 转换      更新时间:2023-10-16

请考虑以下C++代码:

typedef std::string& mutable_string_ref;
const std::string str = "abc";
mutable_string_ref ref(str);

这显然会导致编译器错误,因为您无法创建对 const 字符串的可变引用。 在 GCC 4.7.2 中,产生的错误是:

error: invalid initialization of reference of type ‘mutable_string_ref {aka std::basic_string<char>&}’ from expression of type ‘const string {aka const std::basic_string<char>}’


......为什么如果我们尝试同样的事情,只有我们将引用类型作为模板参数传递,突然它似乎忽略了恒定性?

考虑:

template <class T>
T get()
{
    const static std::string s = "abc";
    return T(s);
}
int main()
{
    std::string& s = get<std::string&>();
    s = "blah"; // undefined behavior!!
}

上面的代码在GCC 4.7.2上编译良好,没有警告。 我不明白它为什么编译。 似乎T(s)的表达基本上被解释为C式的演员阵容,只是抛弃了恒定性。 但是为什么? 我用T = std::string& get实例化了函数模板,所以表达式return T(s)应该无法编译,因为sconst。 然而,它并没有失败。

Ideone link: http://ideone.com/TAO5C6

这是编译器错误吗? 还是有一些正当的理由编译?

你不是在初始化,你是C式的铸造,它确实有能力抛弃恒常性。

从标准:

5.2.3 显式类型转换(函数表示法) [expr.type.conv]

1

简单类型说明符 (7.1.6.2) 或类型名说明符 (14.6) 后跟括号的表达式列表在给定表达式列表的情况下构造指定类型的值。如果表达式列表是单个表达式,则类型转换表达式等效(在定义性上,如果在含义上定义)与相应的强制转换表达式 (5.4) 等效。

5.4 显式类型转换(强制转换表示法)

1 表达式 (T) 转换表达式的结果为 T 类型。