受约束的成员函数和显式模板实例化

2024-04-19

G++ 和 Clang++ 一致认为以下代码片段不是有效的 C++:

template<int dim, int rank>
struct Tensor {};

template<int dim>
double InnerProduct(Tensor<dim, 1> const &, Tensor<dim, 1> const &)
  { return 0.0; }

template<int dim>
double DoubleInnerProduct(Tensor<dim, 2> const &, Tensor<dim, 2> const &)
  { return 0.0; }

template<int dim, int rank>
class Field
{
private:
  static double Dot(Tensor<dim, rank> const &u, Tensor<dim, rank> const &v) requires (rank == 1)
    { return InnerProduct(u, v); }

  static double Dot(Tensor<dim, rank> const &u, Tensor<dim, rank> const &v) requires (rank == 2)
    { return DoubleInnerProduct(u, v); }
};

template class Field<2, 1>;
template class Field<2, 2>;

错误消息指出,即使具有不满足约束的函数也会被实例化:

error: no matching function for call to ‘DoubleInnerProduct(const Tensor<2, 1>&, const Tensor<2, 1>&)’
   22 |     { return DoubleInnerProduct(u, v); }

我可以通过多种方式让它工作(例如,声明Dot作为默认参数等于的模板rank应用了约束),但我希望它能起作用。

一般来说,我是否应该假设具有成员函数(其约束取决于其模板参数)的模板类无法显式实例化?


显式类模板实例化定义也是在实例化点定义的那些成员的显式实例化定义

考虑以下简化示例:

template<int rank>
struct A {};

template<int rank>
struct Field {
    void dot(A<rank>) requires (rank == 1) { (void)(1); }
    void dot(A<rank>) requires (rank == 2) { (void)(2); }
};

[临时显式]/11 http://eel.is/c++draft/temp.explicit#11状态 [emphasis mine]:

显式实例化命名类模板专业化 也是一个显式实例化同类(声明或 定义)其每个成员的(不包括会员 从基类和模板成员继承) 以前没有明确专门从事翻译单元 包含显式实例化,前提是相关的 限制条件,如果有的话,该成员对模板感到满意 显式实例化的参数([temp.constr.decl], [临时.构造.构造]),除下述情况外。 [...]

这意味着仅命名类模板特化的显式实例化定义Field, say

template struct Field<1>;

还将导致显式实例化定义dot满足约束表达式的重载 requires (rank == 1),但不适用于带有约束表达式的重载requires (rank == 2)。但是,那除下述情况外部分引导我们[临时显式]/12 https://eel.is/c++draft/temp.explicit#12,其中指出 [emphasis mine]:

命名类模板的显式实例化定义 专业化显式实例化类模板 专业化并且是显式实例化定义仅有的 那些在实例化时定义的成员.

这意味着,对于上面的简化示例(后跟显式实例化定义)Field<1>,如上),上面的段落表明了显式实例化定义both dot重载,因为两者都已在显式实例化定义时定义Field<1>。然而,这意味着违反 ODR,因为将有两种定义Field<1>::void dot(A<1>).

// Not OK.
template<int rank>
struct A { };

template<int rank>
struct Field {
    void dot(A<rank>) requires (rank == 1) { (void)(1); }
    void dot(A<rank>) requires (rank == 2) { (void)(2); }
};

template struct Field<1>;

int main() {}

在 Clang 上产生以下错误:

error: definition with same mangled name '_ZN5FieldILi1EE3dotE1AILi1EE' as  another definition
       void dot(A<rank>) requires (rank == 2) { }

请注意,我们可以提供显式实例化定义,特别是dot非模板成员Field后者的给定特化的类模板,GCC 和 Clang 会很乐意接受它,这表明在显式实例化重载、约束函数时,会遵守约束表达式:

// OK.
template<int rank>
struct A { };

template<int rank>
struct Field {
    void dot(A<rank>) requires (rank == 1) { (void)(1); }
    void dot(A<rank>) requires (rank == 2) { (void)(2); }
};

template void Field<1>::dot(A<1>);

int main() {}

但如上所述,当它们按照上面的 [temp.explicit]/12 引用隐式给出显式实例化定义时,则不然,因为这似乎为两个成员提供了单独的实例化定义(不考虑约束表达式),从而违反了 ODR 。

类模板专业化的显式实例化定义与专业化的非模板成员函数之间编译器的不同行为有些特殊,但可能的区别在于,对于后一种情况,[临时构造.构造]/2 http://eel.is/c++draft/temp.constr.constr#2.sentence-3适用 [emphasis mine]

[...] 重载解决需要满足功能约束和函数模板。


如果我们只declare但不要定义第二个重载,它不会作为显式实例化定义的一部分进行实例化(即,[临时显式]/12 https://eel.is/c++draft/temp.explicit#12不适用)的Field<1>,我们将不再有 ODR 违规:

// OK.
template<int rank>
struct A { };

template<int rank>
struct Field {
    void dot(A<rank>) requires (rank == 1) { (void)(1); }
    void dot(A<rank>) requires (rank == 2);
};

template struct Field<1>;

int main() {}

现在,为什么隐式实例化不会失败?

As per [温度设置]/3 https://eel.is/c++draft/temp.inst#3.1 [emphasis mine]:

类模板特化的隐式实例化导致

(3.1) 声明的隐式实例化,但不属于 定义,非删除类成员函数中,member 类、作用域成员枚举、静态数据成员、成员 模板和朋友;和 [...]

这样 Clang 和 GCC 都接受以下示例:

template<int rank>
struct A { };

template<int rank>
struct Field {
    void dot(A<rank>) requires (rank == 1) { (void)(1); }
    void dot(A<rank>) requires (rank == 2) { (void)(2); }
};

int main() { 
    Field<1> f{};
    (void)f;
}

其中,根据[温度设置]/4 https://eel.is/c++draft/temp.inst#4, the dot重载不会被实例化为Field<1>专业化不在需要其定义存在的上下文中引用。

然而,最后我们可能会注意到,隐式实例化dot的静态成员函数Field类模板将尊重约束表达式,并实例化满足约束的重载rank特定类模板特化的非模板参数:

#include <iostream>

template<int rank>
struct A { };

template<int rank>
struct Field {
    void dot(A<rank>) requires (rank == 1) { std::cout << "1"; }
    void dot(A<rank>) requires (rank == 2) { std::cout << "2"; } 
};

int main() { 
    Field<1>{}.dot(A<1>{}); // "1"
}

这可能是由[临时构造.构造]/2 http://eel.is/c++draft/temp.constr.constr#2.sentence-3,如上面引用的。

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

受约束的成员函数和显式模板实例化 的相关文章

  • UTF8/UTF16 和 Base64 在编码方面有什么区别

    In c 我们可以使用下面的类来进行编码 System Text Encoding UTF8 System Text Encoding UTF16 System Text Encoding ASCII 为什么没有System Text En
  • 属性对象什么时候创建?

    由于属性实际上只是附加到程序集的元数据 这是否意味着属性对象仅根据请求创建 例如当您调用 GetCustomAttributes 时 或者它们是在创建对象时创建的 或者 前两个的组合 在由于 CLR 的属性扫描而创建对象时创建 从 CLR
  • 如何在 Unity 中从 RenderTexture 访问原始数据

    问题的简短版本 我正在尝试访问 Unity 中 RenderTexture 的内容 我一直在使用 Graphics Blit 使用自己的材质进行绘制 Graphics Blit null renderTexture material 我的材
  • 嵌入式系统中的malloc [重复]

    这个问题在这里已经有答案了 我正在使用嵌入式系统 该应用程序在 AT91SAMxxxx 和 cortex m3 lpc17xxx 上运行 我正在研究动态内存分配 因为它会极大地改变应用程序的外观 并给我更多的力量 我认为我唯一真正的路线是为
  • SSH 主机密钥指纹与模式 C# WinSCP 不匹配

    我尝试通过 WinSCP 使用 C 连接到 FTPS 服务器 但收到此错误 SSH 主机密钥指纹 与模式不匹配 经过大量研究 我相信这与密钥的长度有关 当使用 服务器和协议信息 下的界面进行连接时 我从 WinSCP 获得的密钥是xx xx
  • 如何在我的应用程序中使用 Windows Key

    Like Windows Key E Opens a new Explorer Window And Windows Key R Displays the Run command 如何在应用程序的 KeyDown 事件中使用 Windows
  • 为什么 POSIX 允许在只读模式下超出现有文件结尾 (fseek) 进行搜索

    为什么寻找文件结尾很有用 为什么 POSIX 让我们像示例中那样在以只读方式打开的文件中进行查找 c http en cppreference com w c io fseek http en cppreference com w c io
  • 为什么禁止在 constexpr 函数中使用 goto?

    C 14 对你能做什么和不能做什么有规则constexpr功能 其中一些 没有asm 没有静态变量 看起来相当合理 但标准也不允许goto in constexpr功能 即使它允许其他控制流机制 这种区别背后的原因是什么 我以为我们已经过去
  • 使用 Google Analytics API 在 C# 中显示信息

    我一整天都在寻找一个好的解决方案 但谷歌发展得太快了 我找不到有效的解决方案 我想做的是 我有一个 Web 应用程序 它有一个管理部分 用户需要登录才能查看信息 在本节中 我想显示来自 GA 的一些数据 例如某些特定网址的综合浏览量 因为我
  • c 中的错误:声明隐藏了全局范围内的变量

    当我尝试编译以下代码时 我收到此错误消息 错误 声明隐藏了全局范围内的变量 无效迭代器 节点 根 我不明白我到底在哪里隐藏或隐藏了之前声明的全局变量 我怎样才能解决这个问题 typedef node typedef struct node
  • 使用安全函数在 C 中将字符串添加到字符串

    我想将文件名复制到字符串并附加 cpt 但我无法使用安全函数 strcat s 来做到这一点 错误 字符串不是空终止的 我确实设置了 0 如何使用安全函数修复此问题 size strlen locatie size nieuw char m
  • Windows 窗体不会在调试模式下显示

    我最近升级到 VS 2012 我有一组在 VS 2010 中编码的 UI 测试 我试图在 VS 2012 中启动它们 我有一个 Windows 窗体 在开始时显示使用 AssemblyInitialize 属性运行测试 我使用此表单允许用户
  • 如何在 Team Foundation 上强制发表有意义的签入评论?

    我有一个开发团队有一个坏习惯 他们写道poor签入评论 当我们必须在团队基础上查看文件的历史记录时 这使得它成为一场噩梦 我已经启用了变更集评论政策 这样他们甚至可以在签到时留下评论 否则他们不会 我们就团队的工作质量进行了一些讨论 他们很
  • 初始化变量的不同方式

    在 C 中初始化变量有多种方法 int z 3 与 int 相同z 3 Is int z z 3 same as int z z 3 您可以使用 int z z 3 Or just int z 3 Or int z 3 Or int z i
  • .NET 选项将视频文件流式传输为网络摄像头图像

    我有兴趣开发一个应用程序 它允许我从 xml 构建视频列表 包含视频标题 持续时间等 并将该列表作为我的网络摄像头流播放 这意味着 如果我要访问 ustream tv 或在实时通讯软件上激活我的网络摄像头 我的视频播放列表将注册为我的活动网
  • 作为字符串的动态属性名称

    使用 DocumentDB 创建新文档时 我想设置属性名称动态地 目前我设置SomeProperty 像这样 await client CreateDocumentAsync dbs db colls x new SomeProperty
  • ListDictionary 类是否有通用替代方案?

    我正在查看一些示例代码 其中他们使用了ListDictionary对象来存储少量数据 大约 5 10 个对象左右 但这个数字可能会随着时间的推移而改变 我使用此类的唯一问题是 与我所做的其他所有事情不同 它不是通用的 这意味着 如果我在这里
  • 如何使用 ReactiveList 以便在添加新项目时更新 UI

    我正在创建一个带有列表的 Xamarin Forms 应用程序 itemSource 是一个reactiveList 但是 向列表添加新项目不会更新 UI 这样做的正确方法是什么 列表定义 listView new ListView var
  • 更改显示的 DPI 缩放大小使 Qt 应用程序的字体大小渲染得更大

    我使用 Qt 创建了一些 GUI 应用程序 我的 GUI 应用程序包含按钮和单选按钮等控件 当我运行应用程序时 按钮内的按钮和字体看起来正常 当我将显示器的 DPI 缩放大小从 100 更改为 150 或 200 时 无论分辨率如何 控件的
  • 为什么 strtok 会导致分段错误?

    为什么下面的代码给出了Seg 最后一行有问题吗 char m ReadName printf nRead String s n m Writes OK char token token strtok m 如前所述 读取字符串打印没有问题 但

随机推荐

  • C++:“我的文本”是 std::string、*char 还是 c 字符串?

    我刚刚做了看似的事情新手常见的错误 https stackoverflow com questions 721129 spot the error in this file reading code c 首先我们读到许多教程之一 http
  • Heroku CLI 突然损坏

    突然 从一个命令到下一个命令 Heroic CLI 停止工作 无论我在命令行中输入什么内容 我都会收到相同的错误 见下文 heroku help commands is not a heroku command Perhaps you me
  • boto3 S3 对象解析

    我正在尝试编写一个 Python 脚本来处理存储在 S3 上的音频数据 我有一个 S3 对象 我正在使用它调用 def grabAudio filename directory obj s3client get object Bucket
  • 什么是 java.lang.Class[]

    What is java lang Class Thanks Puneet 参数化类型的类型参数不限于具体的 类或接口 Java 允许使用类型通配符作为 参数化类型的类型参数 通配符是类型参数 以 的形式 可能有上限或下限 鉴于 通配符表示
  • Rscript执行错误:没有那个文件或目录

    Rscript 的二进制文件可用 但当我尝试使用它时 我得到 Rscript helloworld r Rscript execution error No such file or directory 如果我只做 Rscript 它会带来
  • 使用 openCV 查找图像轮廓

    因为我想跟踪物体的运动 所以我需要图像序列的轮廓 有人知道怎么做这个吗 轮廓蒙版是一个二值图像 在运动发生处具有非零像素 您可以使用以下技术背景扣除 这里有两种方法 从当前帧中减去前一帧 只有两个帧中未发生变化的像素才会导致零 看cvSub
  • 使用 Gmail 的 PHP 邮件

    在我的 PHP Web 应用程序中 我希望在发生某些错误时通过电子邮件收到通知 我想使用我的 Gmail 帐户发送这些内容 这怎么可能做到呢 Gmail 的 SMTP 服务器需要非常具体的配置 From Gmail 帮助 http mail
  • 如何将文件从 Ansible Tower 上传到 Artifactory?

    我每次都会收到此错误 但仅在尝试从 Ansible Tower 上传到 Artifactory 时出现在特定文件上 这些文件都是在清单主机上创建的Oracle Collection Tool 然后在上传到 Artifactory 之前获取到
  • 在 Typescript 中声明并初始化字典

    给出以下代码 interface IPerson firstName string lastName string var persons id string IPerson p1 firstName F1 lastName L1 p2 f
  • Bootstrap 容器流体填充

    以下 HTML 生成不需要的填充 div class container fluid div class row div class col xs 12 test div div div 显示问题的屏幕截图 这里的答案都没有帮助我使用 Bo
  • Jenkins 服务始终在 minikube 上挂起

    我安装了minikube在本地 仪表板是 192 168 99 100 30000 我通过 helm 安装了 Jenkins helm install stable jenkins 然后服务始终挂起 kubectl get services
  • 我怎样才能得到dag中的execution_date?运算符的外部?

    我怎样才能获得execution date参数在 dag 之外 execution min execution date strftime M if execution min 00 logging info YES It s 00 fin
  • 如何获取文件相对于 Git 存储库根的路径?

    Example cd lib git absolute path test c how to do this lib test c Use git ls files https www git scm com docs git ls fil
  • 为什么需要锁来实现 readonly int 属性?

    我是线程新手 我遇到了一个自定义线程池实现示例blog http ferruh mavituna com net multithreading ve basit bir threadpool implementasyonu oku 我只粘贴
  • iPad 状态栏有时会消失,留下空白 - 但我从不隐藏它!

    我从不隐藏状态栏 但有时它会消失 这种模式似乎是在一些全屏转换之后发生的 从一个视图水平翻转到另一个视图 使用 QLPreviewController 当它被关闭时 状态栏就会消失 但是 我无法重现它 它只是有时会发生 永远不会在模拟器上
  • 强制 iOS 将 Unicode 符号渲染为平面/文本

    iPhone 现在可以自动将 2D unicode 符号转换为 3D 表情符号 例如 我需要 unicode 以传统的黑白字形格式呈现 而且 我无法轻松地将 Unicode 符号替换为图像 因为这是在 UITableView 行的 edit
  • @Request Mapping 中的生产和消费是什么

    我的项目中有以下代码行 RequestMapping value UrlHandler GET AUTHENTICATION produces application json consumes application json metho
  • 如何从不同列条件下的 PySpark 数据帧中提取数组元素?

    我有以下内容PySpark 输入数据框 index valuelist 1 0 10 20 30 2 0 11 21 31 0 0 14 12 15 Where 索引 双精度型 值列表 类型Vector it s 非数组 从上面的输入数据框
  • 程序加载期间添加的菜单项的 Vcl 样式问题

    我有一个 Delphi 10 4 2 程序 32 位 其中在程序加载期间添加菜单项 Application OnActivate 事件 编码为仅运行一次 如果没有 vcl 样式 新项目将正确显示 但是当应用样式时 例如屏幕截图中非常漂亮的
  • 受约束的成员函数和显式模板实例化

    G 和 Clang 一致认为以下代码片段不是有效的 C template