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++试图通过允许引用“数组类型”来修复这一点。