我正在研究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
我有两个问题:
gcc推导T为int& type
,行const T t = val
意味着t const绑定到val,如下所示:const int &t = val
,为什么const无效? t和i的值可以更改吗?
我用typeid(t).name()
来显示t的类型,为什么只打印i
?
答案 0 :(得分:3)
const T
和T = int&
表示给我一个我无法重新分配的参考。但是,引用永远是不可分配的,它始终指向同一对象。因此它折叠为T
,在这种情况下为int&
。 为使其按预期工作,请使用std::remove_reference
请参阅:const references in c++ templates
name
返回的是实现定义的内容,因此无需多说。 答案 1 :(得分:2)
- gcc推断
T
是int&
类型const T t = val
,意味着t const绑定到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
限定符已被删除。
不需要
- 我用
typeid(t).name()
来显示t的类型,为什么只打印i
?
typeid(t).name()
输出人类可读的标识符。 i
代表int
,因此这取决于您的编译器。当使用clang
或gcc
时,通常最好通过以下方式显示类型
template <class T> p(T&&) { std::cout << __PRETTY_FUNCTION__; }
p(t); // prints out understandable type info
答案 2 :(得分:0)
我写了另一个程序来研究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 T
是int * const
而不是const int *
,因为该编译器将T
视为int
这样的普通类型, char
,而不是int *
,这不是替代。