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

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(使用前将#替换为@)

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

  • 如何以编程方式将访问键(快捷方式)添加到 WPF ContextMenu?

    我已经有以下内容 var myContextMenu new System Windows Controls ContextMenu var exitItem new MenuItem exitItem Header E xit exitI
  • 如何在C++中生成非常大的随机数

    我想使用 C 生成 0 2 64 范围内的非常大的随机数 我已经使用了 rand 函数 但它没有生成非常大的数字 有人可以帮忙吗 使用c 11 使用标准c 11的随机库 http en cppreference com w cpp nume
  • 如何将这段 javascript 代码重写为 C++11?

    这是我在 Javascript Definitive Guide 中看到的 javascript 闭包代码 我想把它写成C 11 var uniqueID1 function var id 0 return function return
  • 无法使用c#更改视频捕获分辨率

    我正在尝试使用 C 中的 DirectShowNet 更改默认网络摄像头分辨率 据我所知 我需要通过调用 windows win32 api dll 中内置的 VideoInfoHeader 类来更改它以进行 avi 捕获 我有来自 Dir
  • 如何在 ASP.NET MVC 中将 XML 文件发送到客户端

    在 ASP NET MVC 中 我有一个数据库表 我想在某个视图页面上有一个按钮 如果某个用户单击该按钮 我的应用程序将生成包含数据库中所有行的 XML 文件 然后 应将包含 XML 的文件发送到客户端 以便用户看到下载弹出窗口 同样 我希
  • 采用 std::vector 或 std::array 的模板函数

    我有一个函数 当前接受 2 个向量 其中可以包含任何普通的旧数据 template
  • 如何通过覆盖 MSBuild 目标来防止外语资源生成?

    我正在致力于减少大型 C ASP NET 解决方案的编译时间 我们的解决方案使用通常的 resx 文件方法翻译成大约十几种外语 这些资源文件的解析和编译极大地减慢了我们的编译时间 并且是日常的挫败感 我知道可以创建自定义资源提供程序并摆脱
  • C# 异步任务比同步慢

    你知道为什么同步斐波那契方法比异步 等待更快并且比异步任务更快吗 我在每个项目方法上都使用了异步 所以主要是这是一个非常糟糕的方法 Code static int FibonacciSync int number if number 0 r
  • 我可以将 char 或 DateTime 设置为 null 吗?

    我可以将 null 设置为char数据类型 并且DateTime在 C 中 多谢你们 这是不可能的 它是一个值类型 使用 char myChar null DateTime myDate null 这相当于 Nullable
  • 从内存流播放视频文件

    只是好奇看看这是否可能 我有一个 Windows 应用程序 它从我的电脑上的 avi 文件读取所有字节 然后将其存储在 byte 中 现在我的内存中有 avi 文件 我想直接从内存将其加载到某种视频播放器控件中 我尝试过使用 wmplaye
  • asp.net core http 如果没有内容类型标头,则删除 `FromBody` 忽略

    我在 http 中使用 bodyDELETE要求 我知道目前删除主体是非标准的 但是允许的 使用时出现问题HttpClient它不允许删除请求的正文 我知道我可以使用SendAsync 但我宁愿让我的 API 更加灵活 我希望这个机构是可选
  • Windows 上本机 C++ 应用程序中的自动死代码检测?

    背景 我有一个用原生 C 编写的应用程序 花了几年的时间 大约有 60 KLOC 有很多函数和类已经死了 可能有 10 15 就像下面提出的类似的基于 Unix 的问题 我们最近开始对所有新代码进行单元测试 并尽可能将其应用于修改后的代码
  • 意外的 const 引用行为

    include
  • 实体框架读取列但阻止其更新

    给定一个数据库表 其中有一列包含历史数据但不再填充 实体框架中是否有一种方法可以读取该列 但在使用相同的模型对象时防止它被更新 例如我有一个对象 public class MyObject public string CurrentData
  • 基础设施 - 同步和异步接口和实现? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 在实现库 基础设施时 并且该 API 的用户希望同步和异步使用代码 我读到混合同步和异步并不是一个好主意 例如 同步实现包括等待异步实现 显然
  • 如何通过代理将套接字连接到http服务器?

    最近 我使用 C 语言编写了一个程序 用于连接到本地运行的 HTTP 服务器 从而向该服务器发出请求 这对我来说效果很好 之后 我尝试使用相同的代码连接到网络上的另一台服务器 例如 www google com 但我无法连接并从网络中的代理
  • 使用任务的经典永无止境的线程循环?

    给出了一个非常常见的线程场景 宣言 private Thread thread private bool isRunning false Start thread new Thread gt NeverEndingProc thread S
  • 使用C标准数学库精确计算标准正态分布的CDF

    标准 C 数学库不提供计算标准正态分布 CDF 的函数 normcdf 然而 它确实提供了密切相关的函数 误差函数 erf 和互补误差函数 erfc 计算 CDF 的最快方法通常是通过误差函数 使用预定义常量 M SQRT1 2 来表示 d
  • 强制函数调用的顺序?

    假设我有一个抽象基类 并且我想要一个必须由派生类实现的纯虚方法 但我想确保派生方法以特定顺序调用函数 我可以做什么来强制执行它 I E base class virtual void doABC 0 virtual void A 0 vir
  • 创建进程默认浏览器

    我目前正在使用 ShellExecute 打开 在用户浏览器中打开 URL 但在 Win7 和 Vista 中遇到了一些麻烦 因为该程序作为服务运行提升 我想获取线程 id 因此 ShellExecute 无法获取线程 id 因此我开始使用

随机推荐

  • 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