当函数参数是对 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 的模板参数推导会“跳过”数组元素的常量性? 的相关文章

  • 通过引用传递 [C++]、[Qt]

    我写了这样的东西 class Storage public Storage QString key const int value const void add item QString int private QMap
  • 如何在 C# 中打开 Internet Explorer 属性窗口

    我正在开发一个 Windows 应用程序 我必须向用户提供一种通过打开 IE 设置窗口来更改代理设置的方法 Google Chrome 使用相同的方法 当您尝试更改 Chrome 中的代理设置时 它将打开 Internet Explorer
  • free 和 malloc 在 C 中如何工作?

    我试图弄清楚如果我尝试 从中间 释放指针会发生什么 例如 看下面的代码 char ptr char malloc 10 sizeof char for char i 0 i lt 10 i ptr i i 10 ptr ptr ptr pt
  • 传递给函数时多维数组的指针类型是什么? [复制]

    这个问题在这里已经有答案了 我在大学课堂上学习了 C 语言和指针 除了多维数组和指针之间的相似性之外 我认为我已经很好地掌握了这个概念 我认为由于所有数组 甚至多维 都存储在连续内存中 因此您可以安全地将其转换为int 假设给定的数组是in
  • 从经典 ASP 调用 .Net C# DLL 方法

    我正在开发一个经典的 asp 项目 该项目需要将字符串发送到 DLL DLL 会将其序列化并发送到 Zebra 热敏打印机 我已经构建了我的 DLL 并使用它注册了regasm其次是 代码库这使得 IIS 能够识别它 虽然我可以设置我的对象
  • -webkit-box-shadow 与 QtWebKit 模糊?

    当时有什么方法可以实现 webkit box shadow 的工作模糊吗 看完这篇评论错误报告 https bugs webkit org show bug cgi id 23291 我认识到这仍然是一个问题 尽管错误报告被标记为RESOL
  • 如何在 C++ 中标记字符串?

    Java有一个方便的分割方法 String str The quick brown fox String results str split 在 C 中是否有一种简单的方法可以做到这一点 The 增强分词器 http www boost o
  • 对类 static constexpr 结构的未定义引用,g++ 与 clang

    这是我的代码 a cp p struct int2 int x y struct Foo static constexpr int bar1 1 static constexpr int2 bar2 1 2 int foo1 return
  • C++ 多行字符串原始文字[重复]

    这个问题在这里已经有答案了 我们可以像这样定义一个多行字符串 const char text1 part 1 part 2 part 3 part 4 const char text2 part 1 part 2 part 3 part 4
  • 两个静态变量同名(两个不同的文件),并在任何其他文件中 extern 其中一个

    在一个文件中将变量声明为 static 并在另一个文件中进行 extern 声明 我认为这会在链接时出现错误 因为 extern 变量不会在任何对象中看到 因为在其他文件中声明的变量带有限定符 static 但不知何故 链接器 瑞萨 没有显
  • 结构体的内存大小不同?

    为什么第一种情况不是12 测试环境 最新版本的 gcc 和 clang 64 位 Linux struct desc int parts int nr sizeof desc Output 16 struct desc int parts
  • 两个类可以使用 C++ 互相查看吗?

    所以我有一个 A 类 我想在其中调用一些 B 类函数 所以我包括 b h 但是 在 B 类中 我想调用 A 类函数 如果我包含 a h 它最终会陷入无限循环 对吗 我能做什么呢 仅将成员函数声明放在头文件 h 中 并将成员函数定义放在实现文
  • 从 pygame 获取 numpy 数组

    我想通过 python 访问我的网络摄像头 不幸的是 由于网络摄像头的原因 openCV 无法工作 Pygame camera 使用以下代码就像魅力一样 from pygame import camera display camera in
  • C 编程:带有数组的函数

    我正在尝试编写一个函数 该函数查找行为 4 列为 4 的二维数组中的最大值 其中二维数组填充有用户输入 我知道我的主要错误是函数中的数组 但我不确定它是什么 如果有人能够找到我出错的地方而不是编写新代码 我将不胜感激 除非我刚去南方 我的尝
  • 如何实例化 ODataQueryOptions

    我有一个工作 简化 ODataController用下面的方法 public class MyTypeController ODataController HttpGet EnableQuery ODataRoute myTypes pub
  • 如何在 Linq to SQL 中使用distinct 和 group by

    我正在尝试将以下 sql 转换为 Linq 2 SQL select groupId count distinct userId from processroundissueinstance group by groupId 这是我的代码
  • C 函数 time() 如何处理秒的小数部分?

    The time 函数将返回自 1970 年以来的秒数 我想知道它如何对返回的秒数进行舍入 例如 对于100 4s 它会返回100还是101 有明确的定义吗 ISO C标准没有说太多 它只说time 回报 该实现对当前日历时间的最佳近似 结
  • 有没有办法让 doxygen 自动处理未记录的 C 代码?

    通常它会忽略未记录的 C 文件 但我想测试 Callgraph 功能 例如 您知道在不更改 C 文件的情况下解决此问题的方法吗 设置变量EXTRACT ALL YES在你的 Doxyfile 中
  • C++ 继承的内存布局

    如果我有两个类 一个类继承另一个类 并且子类仅包含函数 那么这两个类的内存布局是否相同 e g class Base int a b c class Derived public Base only functions 我读过编译器无法对数
  • 在OpenGL中,我可以在坐标(5, 5)处精确地绘制一个像素吗?

    我所说的 5 5 正是指第五行第五列 我发现使用屏幕坐标来绘制东西非常困难 OpenGL 中的所有坐标都是相对的 通常范围从 1 0 到 1 0 为什么阻止程序员使用屏幕坐标 窗口坐标如此严重 最简单的方法可能是通过以下方式设置投影以匹配渲

随机推荐