当函数参数是对 T 的 const 引用时,为什么 T 的模板参数推导会“跳过”数组元素的常量性?

2024-01-05

让我们考虑一下这些定义:

/*** 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 的指针

如果执行以下语句:

const int i=5, *ip=&i;
func(ip);

输出是:

Deduced type for T is: 4TypeI**PKi**E

So T实际上被推导为指向常量整数的指针。参数是对 const 的引用这一事实不会改变推论,这是人们所期望的,因为指针的常量是低级的。

但使用 const 数组

尽管如此,如果执行以下语句:

const int ia[3] = {3, 2, 1};
func(ia);

输出是:

Deduced type for T is: 4TypeI**A3_i**E

So T实际上被推导出为 3 的数组non-常量整数。事实上,参数是对 const 的引用确实改变了的扣除,就好像const正在滑入数组元素。

实际上,18 之前的 CL 版本都在推导T因为 3 个常量整数的数组是我期望的标准,但似乎自 v19 以来它收敛到 GCC 和 Clang 正在做的事情(即推导为non-const).

因此,我认为后来的行为是标准的,但这是基本原理吗?它的行为与指针不同,这似乎令人惊讶。


Edit:下列的dip评论,我将在这里报告与此行为相关的 CWG 问题的指针,他实际上作为评论发布的指针这个答案 https://stackoverflow.com/a/30866205/1027706(实际上提出了这个新问题的答案...... C++ 感觉就像一条很深的隧道)

  • CWG 1059 http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1059
  • CWG 1610 http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_active.html#1610
  • CWG 112 http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#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元素。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当函数参数是对 T 的 const 引用时,为什么 T 的模板参数推导会“跳过”数组元素的常量性? 的相关文章

随机推荐