当函数参数常量引用 T 时,为什么 T 的模板参数推导'skips'数组元素的恒定性?
Why does template parameter deduction for T 'skips' the constness of array elements when function parameter is const reference to 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;
}
带有指向常量的指针
如果执行以下语句:
const int i=5, *ip=&i;
func(ip);
输出为:
Deduced type for T is: 4TypeI**PKi**E
因此,T
实际上被推导为指向常量整数的指针。参数是对常量的引用这一事实不会改变推论,这是人们所期望的,因为指针的恒定性是低级的。
但带有常量数组
尽管如此,如果执行以下语句:
const int ia[3] = {3, 2, 1};
func(ia);
输出为:
Deduced type for T is: 4TypeI**A3_i**E
因此,T
实际上被推导为一个由 3 个非常量整数组成的数组。参数是对常量的引用这一事实确实改变了推论,就好像const
滑入数组元素一样。
实际上,高达 18 的 CL 版本正在推导出T
因为 3 个常量整数的数组是我期望的标准,但似乎自 v19 以来,它收敛到 GCC 和 Clang 正在做的事情(即,推断为非常量)。
因此,我认为后来的行为是标准的,但理由是什么?令人惊讶的是,它的行为与指针不同。
编辑:在dip评论之后,我将在这里报告与此行为相关的CWG问题的指针,他实际上发布的指针作为对此答案的评论(实际上提出了这个新问题的答案......C++感觉就像一个深隧道)
- CWG 1059
- CWG 1610
- CWG 112
使用此函数模板原型:
template <typename T> void func(const T& a);
在第一个示例中,类型推断的工作方式为:
const int* ip;
func(ip) => func<const int*>(const (const int*)& a)
^^^^^^^^^^ ^^^^^^^^^^
注意:这是伪代码。完整类型为 const int* const&
。
请注意,const int
保持const int
,但*
变为* const
。
这是因为const int*
只是一个常规的、可变的、非易失性的指针。这只是一个*
.它所指向的内容无关紧要。
但在第二个示例中,您有:
const int ia[3];
func(ia) => func<int[3]>(const (int[3])& a)
^^^^^^ ^^^^^^
注意:这是伪代码。真正的类型将是const int (&a)[3]
.
因此,类型推断在两种情况下的工作方式相同,丢弃了外部const
。
碰巧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])
在第二个示例中,const
似乎从应用于数组"移动"到应用于元素。这是因为你不能真正有一个const
数组,只有一个const
元素的数组。
- 如何反转整数参数包
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 如何使用默认参数等选择模板专业化
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- 指针类型类成员的动态强制转换的恒定性是什么?
- 自动模板参数、数据成员和恒常性
- 为什么对引用的常量引用会失去其恒定性?
- 运算符的要求<恒定性在标准::stable_sort
- 模板参数推导由于恒定性不一致而失败
- 为什么模板参数失去恒定性?
- 为什么普遍引用不保持其论点的恒定性
- 是否可以使用 SFINAE 检测类方法的恒定性?
- 在模板中强制转换为引用似乎会抛弃恒定性
- 在分配对象时保持恒定性
- 常量成员函数中模板成员的恒定性
- 变量的恒定性及其生存期
- 尊重恒定性,同时避免在堆上重新分配
- 参考类成员的恒定性
- 当函数参数常量引用 T 时,为什么 T 的模板参数推导'skips'数组元素的恒定性?