模板对象的模板友元函数和命名空间

2024-01-03

在以下 C++ 示例代码中,GCC 6 和 Clang 3.8 对正确行为的看法不一致:

这个人为的例子“有效”——如test()函数返回o.p在海湾合作委员会。在 clang 中,它调用(未定义)函数get<int, int, float, double>:

template<typename ...Args>
class obj {
 bool p = false;

 template<typename T, typename... Args2>
 friend T get(const obj<Args2...> &o) { return o.p; }
};

template<typename T, typename... Args>
T get(const obj<Args...> &o);


bool test(const obj<int, float, double> &a) {
 return get<int>(a);
}

将相同的代码放在命名空间中会导致 GCC 执行 clang 所做的相同操作。

namespace ns {

template<typename ...Args>
class obj {
 bool p = false;

 template<typename T, typename... Args2>
 friend T get(const obj<Args2...> &o) { return o.p; }
};

template<typename T, typename... Args>
T get(const obj<Args...> &o);

}

bool test(const ns::obj<int, float, double> &a) {
 return ns::get<int>(a);
}

https://godbolt.org/g/sWrXQO https://godbolt.org/g/sWrXQO and https://godbolt.org/g/9tIXwe https://godbolt.org/g/9tIXwe

哪个编译器是“正确的”并且通常有一种方法define内联友元成员模板函数,无需声明它然后单独定义它。也就是说,像这样的事情:

struct Foo {
 friend bool bar() { return true; } // declares *and* defines a free function bar
 template<typename T> T bar2() { return true; }  // doesn't work!
};

有两个未解决的问题friend类模板中定义的函数模板:1545 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1545 and 2174 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2174。前者质疑其有效程度,后者涉及基于这些函数模板的实际实例可能出现的 ODR 违规。我不确定哪个编译器是正确的(之前认为两者都是错误的),但标准中可能只是未充分或不明确地指定在这种情况下正确的行为是什么。

代码should理想情况下编译(待解决问题):

template<typename ...Args>
class obj {
 bool p = false;

 template<typename T, typename... Args2>
 friend T get(const obj<Args2...> &o) { return o.p; }
};

template<typename T, typename... Args>
T get(const obj<Args...> &o);

The friend声明首先声明get,因此这会创建最内层封闭命名空间的新成员:::get。外部声明只是重新声明相同的函数,因此实际上只有一个::get。来自[temp.over.link]:

如果两个函数定义包含以下内容,则两个涉及模板参数的表达式被视为等效 表达式将满足单一定义规则(3.2),除了用于命名的标记 只要用于在一个表达式中命名模板参数的标记是相同的,模板参数就可以不同 替换为在另一个表达式中命名相同模板参数的另一个标记。用于确定 两个从属名称 (14.6.2) 是否等效,仅考虑名称本身,而不考虑模板上下文中名称查找的结果。

使用不同的模板参数名称(Args... vs Args2...) 很好 - 函数模板的第二个声明::get有效并允许查找找到它。

这让我们想到:

bool test(const obj<int, float, double> &a) {
#ifdef UNQUAL
    return get<int>(a);     // unqualified
#else
    return ::get<int>(a);   // qualified
#endif
}

这两个should工作 - 因为我们将函数重新声明在命名空间范围内,所以我们甚至不必担心 ADL。两次调用都应该找到::get<int>(obj<int, float, double> ),这是一个friend,因此代码应该编译和链接。 gcc 允许不合格的调用,但不允许合格的调用,clang 两者都不允许。

我们可以完全回避这两个 CWG 问题,方法是:not在类中定义函数模板:

template<typename ...Args>
class obj {
 bool p = false;

 template<typename T, typename... Args2>
 friend T get(const obj<Args2...> &o);
};

template<typename T, typename... Args>
T get(const obj<Args...> &o) { return o.p; }

通过这个公式,两种编译都允许both合格和不合格的调用get.


如果我们重写代码obj是一个类而不是类模板,但其他条件相同:

class obj {
    bool p = false;

    template <class T>
    friend T get(const obj& o) { return o.p; }
};

template <class T> T get(const obj& );

bool test(const obj& a) {
#ifdef UNQUAL
    return get<int>(a);
#else
    return ::get<int>(a);
#endif
}

两个编译器都允许这两种调用。但据我所知,两者之间的规则没有区别obj是一个普通的类和一个类模板。

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

模板对象的模板友元函数和命名空间 的相关文章

  • 如何在MVVM中管理多个窗口

    我知道有几个与此类似的问题 但我还没有找到明确的答案 我正在尝试深入研究 MVVM 并尽可能保持纯粹 但不确定如何在坚持模式的同时启动 关闭窗口 我最初的想法是向 ViewModel 发送数据绑定命令 触发代码来启动一个新视图 然后通过 X
  • 如何验证文件名称在 Windows 中是否有效?

    是否有一个 Windows API 函数可以将字符串值传递给该函数 该函数将返回一个指示文件名是否有效的值 我需要验证文件名是否有效 并且我正在寻找一种简单的方法来完成此操作 而无需重新发明轮子 我正在直接使用 C 但针对的是 Win32
  • 无法使用已与其底层 RCW 分离的 COM 对象。在 oledb 中

    我收到此错误 但我不知道我做错了什么 下面的代码在backrgroundworker中 将异常详细信息复制到剪贴板 System Runtime InteropServices InvalidComObjectException 未处理 通
  • 当我使用“control-c”关闭发送对等方的套接字时,为什么接收对等方的套接字不断接收“”

    我是套接字编程的新手 我知道使用 control c 关闭套接字是一个坏习惯 但是为什么在我使用 control c 关闭发送进程后 接收方上的套接字不断接收 在 control c 退出进程后 发送方的套接字不应该关闭吗 谢谢 我知道使用
  • UML类图:抽象方法和属性是这样写的吗?

    当我第一次为一个小型 C 项目创建 uml 类图时 我在属性方面遇到了一些麻烦 最后我只是将属性添加为变量 lt
  • 如何避免情绪低落?

    我有一个实现状态模式每个状态处理从事件队列获取的事件 根据State因此类有一个纯虚方法void handleEvent const Event 事件继承基础Event类 但每个事件都包含其可以是不同类型的数据 例如 int string
  • 如何在列表框项目之间画一条线

    我希望能够用水平线分隔列表框中的每个项目 这只是我用于绘制项目的一些代码 private void symptomsList DrawItem object sender System Windows Forms DrawItemEvent
  • WPF 中的调度程序和异步等待

    我正在尝试学习 WPF C 中的异步编程 但我陷入了异步编程和使用调度程序的困境 它们是不同的还是在相同的场景中使用 我愿意简短地回答这个问题 以免含糊不清 因为我知道我混淆了 WPF 中的概念和函数 但还不足以在功能上正确使用它 我在这里
  • 为什么#pragma optimize("", off)

    我正在审查一个 C MFC 项目 在某些文件的开头有这样一行 pragma optimize off 我知道这会关闭所有以下功能的优化 但这样做的动机通常是什么 我专门使用它来在一组特定代码中获得更好的调试信息 并在优化的情况下编译应用程序
  • C# 中的递归自定义配置

    我正在尝试创建一个遵循以下递归结构的自定义配置部分
  • Github Action 在运行可执行文件时卡住

    我正在尝试设置运行google tests on a C repository using Github Actions正在运行的Windows Latest 构建过程完成 但是当运行测试时 它被卡住并且不执行从生成的可执行文件Visual
  • for循环中计数器变量的范围是多少?

    我在 Visual Studio 2008 中收到以下错误 Error 1 A local variable named i cannot be declared in this scope because it would give a
  • Discord.net 无法在 Linux 上运行

    我正在尝试让在 Linux VPS 上运行的 Discord net 中编码的不和谐机器人 我通过单声道运行 但我不断收到此错误 Unhandled Exception System Exception Connection lost at
  • 控制到达非 void 函数末尾 -wreturn-type

    这是查找四个数字中的最大值的代码 include
  • 将文本叠加在图像背景上并转换为 PDF

    使用 NET 我想以编程方式创建一个 PDF 它仅包含一个背景图像 其上有两个具有不同字体和位置的标签 我已阅读过有关现有 PDF 库的信息 但不知道 如果适用 哪一个对于如此简单的任务来说最简单 有人愿意指导我吗 P D 我不想使用生成的
  • Process.Start 阻塞

    我正在调用 Process Start 但它会阻止当前线程 pInfo new ProcessStartInfo C Windows notepad exe Start process mProcess new Process mProce
  • C 中的异或运算符

    在进行按位操作时 我在确定何时使用 XOR 运算符时遇到一些困难 按位与和或非常简单 当您想要屏蔽位时 请使用按位 AND 常见用例是 IP 寻址和子网掩码 当您想要打开位时 请使用包含或 然而 XOR 总是让我明白 我觉得如果在面试中被问
  • 限制C#中的并行线程数

    我正在编写一个 C 程序来生成并通过 FTP 上传 50 万个文件 我想并行处理4个文件 因为机器有4个核心 文件生成需要更长的时间 是否可以将以下 Powershell 示例转换为 C 或者是否有更好的框架 例如 C 中的 Actor 框
  • 防止索引超出范围错误

    我想编写对某些条件的检查 而不必使用 try catch 并且我想避免出现 Index Out of Range 错误的可能性 if array Element 0 Object Length gt 0 array Element 1 Ob
  • 使用按位运算符相乘

    我想知道如何使用按位运算符将一系列二进制位相乘 但是 我有兴趣这样做来查找二进制值的十进制小数值 这是我正在尝试做的一个例子 假设 1010010 我想使用每个单独的位 以便将其计算为 1 2 1 0 2 2 1 2 3 0 2 4 虽然我

随机推荐

  • Lookahead 正则表达式无法找到相同的重叠匹配项

    再次搜索相同模式时是否可以使用正则表达式找到重叠匹配项 我希望能够找到出现三次的匹配项 例如babab中出现 3 次babababab babababab babababab babababab 这是我当前的 Python 实现 impor
  • 调试多线程应用程序

    我继承了一个在启动时抛出 100 个线程的应用程序 这使得我的调试生活变得极其棘手 有没有一种方法可以让 Visual Studio 遵循一个线程 您是否尝试过在 Visual Studio 中使用 线程 窗口 在 调试 Windows 菜
  • 关键字“Table”附近的语法不正确 C# SQL [关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 您好 我正在尝试找出为什么出现此错误 关键字 Table 附近的语法不正确 提前谢谢 Code using System usin
  • 如何使用 Homebrew 在 OS X 上安装 Python 3.3(不是 3.4)?

    如果你通过 Homebrew 安装 python3 它会默认安装最新版本 我就是这么做的 但我想要 3 3 而不是 3 4 如何专门使用 Homebrew 将其替换为 3 3 我想尝试使用 Python 3 来使用 Django 但我刚刚学
  • 如何在 C# 中创建非持久(在内存中)http cookie?

    我希望我的 cookie 在用户关闭浏览器时消失 我已经设置了一些看起来很有希望的属性 但即使关闭整个浏览器 我的 cookie 也会弹出来 HttpCookie cookie new HttpCookie mycookie abc coo
  • 不同长度的中断和标签scale_size_binned

    我可能在这里遗漏了一些东西 但在任何地方都找不到任何好的例子 R 版本 4 03 ggplot v 3 3 2 尝试让scale size binned 标签正常工作 但不断出现错误 library tidyverse set seed 1
  • 如何以反应形式获取下拉列表的选定值

    我正在尝试获取要在反应式表单提交时发送的更改事件下拉列表的选定值 根据来自的答案 我有一个非常相似的无线电工作场景如何以反应形式获取无线电的选定值 https stackoverflow com questions 48471846 how
  • 在js中找到多边形的中心点

    我找到了一个不错的example http local wasp uwa edu au pbourke geometry polyarea 如何找到多边形的中心点 在 JS 中 http local wasp uwa edu au pbou
  • 动态 ResourceBundle 键的 EL 中的字符串串联

    我有一个资源包 其中包含如下条目 entry1 value1 entry2 value2 entry3 value3 在我的 JSF 页面中 我尝试动态使用这些键 条目的 ID 来自托管 bean 我认为应该是这样的
  • preg_match_all - 正则表达式查找字符串中的完整网址

    我花了 4 个多小时试图为我的 php 代码找到正则表达式模式 但没有运气 我有一个带有 html 代码的字符串 它有很多 url 格式 例如 example com http example com http www example co
  • 在对 pandas 数据帧进行子集化时忽略 KeyError

    我有一个带有列的 pandas 数据框 dfcity1 city2 city3 city4 city5 我有一个清单my cities city1 city3 city10 我想根据中的列对 df 进行子集化my cities 当我做 my
  • 在 MatLab 中将矩阵的列与 3d 矩阵的 2d 矩阵切片相乘

    基本上 我想执行以下计算 G is m x n x k S is n x k Answer zeros m d for Index 1 k Answer Index G Index S Index end 因此 答案是一个矩阵 其列是 3d
  • 如何在 C++ 中读取带有逗号分隔值的流?

    我想强调一个基本问题 假设您有一个 CSV 文件并使用输入标题填充单元格 该代码应从 csv 文件读取此内容并将结果写入 csv 文件 最好还对输出案例总数以及案例平均值进行编码 这是一个示例表单 我想看看如何有效地采用它来完成这个基本示例
  • ggplot 具有不同页面布局的一份 pdf 的绘图列表

    我想生成一个包含许多页 ggplots 的 pdf 文件 使用gridExtra 我还可以用 a 构建一个绘图页面m x n布局 m一排排的地块 n地块列 功能ggsave允许我写一页图 甚至是那些用gridExtra拥有m x n lay
  • 使用 AJAX 加载异地内容

    我正在构建一个 PHP 页面 它将把一些场外内容加载到 DIV 中 页面上还有其他静态元素 我遇到的问题是页面加载时间太长 因为 PHP 在显示页面之前加载站外内容 我正在考虑通过 AJAX 加载 DIV 中的场外内容 我假设无论 AJAX
  • 多部分 POST 请求 Google Glass

    我正在尝试使用多部分编码将附件添加到我的时间线 我一直在做类似以下的事情 req urllib2 Request url data body header header resp urllib2 urlopen req read 它对于 a
  • 在 LaTeX 文档中使用 tikzDevice 和 knit 进行 R 绘图

    我在使 ggplot2 tikzDevice 和 knit 一起工作时遇到问题 我正在使用 RStudio 并尝试在 Latex 文档中包含一些 R 图形 我用了一个非常简单的例子 documentclass article begin d
  • 韩国 Google 地图样式

    我有一个网站 我使用了样式化的谷歌地图 如果您将地图移至韩国 则没有地图特征 道路 高速公路 地点 只有命名城市和一些自治市边界 如果我删除样式 所有这些功能都会恢复 我对哪个功能进行样式设置似乎并不重要 这种情况在应用第一个更改时就会发生
  • 如何在 Mac OS 安装上停止 MySQL?

    我通过安装MySQLMacPorts http en wikipedia org wiki MacPorts 我需要什么命令来停止服务器 我需要测试当 MySQL 死机时我的应用程序的行为 根据您是否安装 有不同的情况MySQL http
  • 模板对象的模板友元函数和命名空间

    在以下 C 示例代码中 GCC 6 和 Clang 3 8 对正确行为的看法不一致 这个人为的例子 有效 如test 函数返回o p在海湾合作委员会 在 clang 中 它调用 未定义 函数get