C++ 为什么T';跳过&x27;当函数参数是对T的常量引用时数组元素的常量? 让我们考虑这些定义: /*** full type information with typeid ***/ template <class> class Type{}; template <class T> std::string typeStr() { return typeid(Type<T>).name(); } /*** function template for parameter deduction ***/ template <class T> void func(const T &a) { std::cout << "Deduced type for T is: " << typeStr<T>() << std::endl; std::cout << "\targument type is: " << typeStr<decltype(a)>() << std::endl; }
输出为:C++ 为什么T';跳过&x27;当函数参数是对T的常量引用时数组元素的常量? 让我们考虑这些定义: /*** full type information with typeid ***/ template <class> class Type{}; template <class T> std::string typeStr() { return typeid(Type<T>).name(); } /*** function template for parameter deduction ***/ template <class T> void func(const T &a) { std::cout << "Deduced type for T is: " << typeStr<T>() << std::endl; std::cout << "\targument type is: " << typeStr<decltype(a)>() << std::endl; },c++,arrays,template-argument-deduction,C++,Arrays,Template Argument Deduction,输出为: Deduced type for T is: 4TypeI**PKi**E Deduced type for T is: 4TypeI**A3_i**E 所以T实际上是一个指向常量整数的指针。参数是对const的引用这一事实并没有改变推断,这是人们所期望的,因为指针的constanness是低级的 但是使用常量数组 尽管如此,如果执行以下语句: const int i=5, *ip=&i; func(ip); const int ia[3] = {3, 2, 1}; fu
Deduced type for T is: 4TypeI**PKi**E
Deduced type for T is: 4TypeI**A3_i**E
所以T
实际上是一个指向常量整数的指针。参数是对const的引用这一事实并没有改变推断,这是人们所期望的,因为指针的constanness是低级的
但是使用常量数组
尽管如此,如果执行以下语句:
const int i=5, *ip=&i;
func(ip);
const int ia[3] = {3, 2, 1};
func(ia);
输出为:Deduced type for T is: 4TypeI**PKi**E
Deduced type for T is: 4TypeI**A3_i**E
所以T
实际上是由3个非常量整数组成的数组。参数是对const的引用这一事实确实改变了推断,就好像const
滑入数组元素一样
实际上,直到18个版本的CL都在推导T
,因为3个常量整数的数组是我期望的标准数组,但似乎从v19开始,它收敛到了GCC和Clang正在做的事情(即,推导为非-const)
因此,我假设后面的行为是标准的,但其基本原理是什么?它的行为与指针不同,这似乎令人惊讶
< >编辑:下面的DIP评论,我将在这里报告与CWG有关的行为的指针,他实际发布的评论(实际提出这个问题的答案…C++感觉像一个深通道)
template <typename T> void func(const T& a);
注意:这是伪代码。真正的类型应该是const int(&a)[3]
因此,类型推断在这两种情况下都是一样的,丢弃了外部的常量
恰好const
数组与const
元素数组相同
这样编写类型可能会有所帮助:
template <typename T> func(T const & a);
int const * ip;
func(ip) => func<int const *>(int const * const & a)
int const ia [3];
func(ia) => func<int [3]>(int const (& a) [3])
模板函数(T const&a);
int const*ip;
func(ip)=>func(int const*const&a)
int const ia[3];
func(ia)=>func(int常量(&a)[3])
在第二个示例中,const
似乎从应用于数组“移动”到应用于元素。这是因为你不能真正拥有一个const
数组,只有const
元素的数组。顶级限定符从typeid
@KerrekSB中被丢弃,在哪种上下文中会被丢弃?(可能您没有看到前两个定义,因为Alf实现了使用typeid
保存完整类型信息的技巧)。引用常量整数数组的类型与引用常量整数数组的类型相同。设X=int[3]
和Y=int const[3]
,则X const&
为const int(&)[3]
为int const(&)[3]
为Y&
。指针的情况并非如此。因此,这似乎并不奇怪:标准可能会指定它以某种方式运行,但我认为为T
推导const int[3]
将是标准中的一个(小的?)缺陷(为什么推导冗余const
?)@dyp谢谢,问题已编辑。我最初没有发布它们,因为我想象你们会把它们放在一个答案中:“@ KerrekSB”,一个数组元素类型的CV限定也被认为与它的元素具有相同的CV资格。“(N496)我将要评论< <代码> const(int [3)]和< /C> >不是C++类型,但是你把注释加了更快!但是我不明白你所说的:“注意,const int
变成int
,而*
变成*const
”是什么意思。在第一个示例中,似乎没有丢弃任何const
。@AdN:)我在这两种类型中使用的括号也是无效的。@AdN抱歉,我不是早起的人。修正了答案,但它并没有改变任何事情。外部级别const
始终被丢弃。问题是C++的由内而外类型系统,这意味着const int*
中的const
不是外部级别const
。事实上,类型const int*
没有CV限定符。它只是一个常规的、可变的、非易失性的指针。我最感兴趣的(部分)问题是应用于元素类型的cv限定符>与应用于数组的>之间的等价原理type@dyp这是因为数组不是C或C++中的真实类型。当然,您可以typedef
它们,但是您不能复制它们,不能移动它们,不能从函数返回它们,以及。。。无法对其应用CV限定符。数组仅仅存在于类型系统之外。C++试图通过允许引用“数组类型”来修复这一点。