在模板中转换为引用似乎抛弃了const-ness

时间:2014-02-23 19:05:11

标签: c++

考虑以下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>}’


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

考虑:

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样式的强制转换,只是抛弃了const-ness。但为什么?我使用get实例化了函数模板T = std::string&,因此表达式return T(s)应该无法编译,因为sconst。但它并没有失败。

Ideone链接:http://ideone.com/TAO5C6

这是编译器错误吗?或者这个编译是否有正当理由?

1 个答案:

答案 0 :(得分:3)

你没有初始化,你是C风格的投射,它确实能够抛弃常数。

来自标准:

  

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

     

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

     

5.4显式类型转换(强制转换符号)

     

1 表达式(T)cast-expression的结果是T型。[...]