为什么不能在模板函数中向局部变量添加低级 const 类型



我正在研究 c++ 模板,并编写如下所示的示例:

#include <vector>
#include <iostream>
#include <type_traits>
#include <typeinfo>
using namespace std;
template <typename T>
void fcn(T &&val)
{
cout << is_same<T, int&>::value << endl;
const T t = val;
//T const t = val;
cout << typeid(t).name() << endl;
t = 10;
cout << "val: " << val;
cout << ", t: " << t << endl;
return;
}
int main()
{
cout << boolalpha;
int i{};
fcn(i);
}

我希望这段代码无法成功编译,但没有错误,输出:

true
i
val: 10, t: 10

我有两个问题:

  1. gcc推导出T是int& typeconst T t = val行,表示t常量绑定到val,像这样:const int &t = val,为什么常量没有效果? t 和 i 值可以改变吗?

  2. 我用typeid(t).name()来显示t的类型,为什么只打印i

  1. 在你的情况下,const TT = int&手段,给我一个我无法重新分配的参考。但是引用永远不可分配,它总是指向同一个对象。所以它坍缩到T,在这种情况下是int&

要使其按预期工作,请使用std::remove_reference

请参阅: C++ 模板中的常量引用

  1. name返回实现定义的内容,因此没有太多可说的。
  1. gcc 推断Tint&类型,const T t = val表示 t 常量绑定到 val,为什么const没有效果?

此函数模板签名

template <typename T> void fcn(T &&val);

使用转发引用。简而言之,当用左值int推导实例化时(您的情况),您最终会得到T = int&,即包括引用。引用折叠将void fcn(T& &&val)转换为void fcn(T& val)

当你声明const T t时,这意味着T& const(const修改它左边的东西,如果它左边什么都没有,它修改它右边的东西)。但这无效,因为没有const限定引用这样的东西,因此删除了const限定符。

  1. 我用typeid(t).name()来显示t的类型,为什么只打印i

typeid(t).name()不需要输出人类可读的标识符。i代表int,因此根据编译器的不同,这是您应该期望的。当使用clanggcc时,通过显示类型通常更好

template <class T> p(T&&) { std::cout << __PRETTY_FUNCTION__; }
p(t); // prints out understandable type info

我编写了另一个程序来研究使用"类型别名"const T

#include <iostream>                                                                                 
using namespace std; 
int main()                                                                                          
{
int i {};
using T = int *;                                                                                
const T t = &i;     // same with T const t = &i;                                                                                                                                                                                                                                     
*t = 10;                                                                                                                                                                                                                                                                             
cout << i << endl;                                                                                                                                                                                                                                                                   
int j{};                                                                                                                                                                                                                                                                             
//t = &j;   // error, t is int * const                                                                                                                                                                                                                                                
} 

编译成功,输出:10.

现在我可以理解为什么编译器认为const Tint * const,而不是const int *,因为编译器将T视为像intchar,而不是int *一样的常见类型,它不是替换。

最新更新