C++ 和 D 中的元编程

2023-12-31

C++ 中的模板机制只是意外地对模板元编程有用。另一方面,D 是专门为促进这一点而设计的。显然它更容易理解(或者我听说过)。

我没有使用 D 的经验,但我很好奇,当涉及到模板元编程时,在 D 中可以做什么而在 C++ 中不能做什么?


在 D 中帮助模板元编程的两个最重要的事情是模板约束和static if- 从理论上讲,C++ 可以添加这两者,并且这将使其受益匪浅。

模板约束允许您在模板上放置一个条件,该条件必须为真才能实例化模板。例如,这是其中一位的签名std.algorithm.find的重载:

R find(alias pred = "a == b", R, E)(R haystack, E needle)
    if (isInputRange!R &&
        is(typeof(binaryFun!pred(haystack.front, needle)) : bool))

为了能够实例化此模板化函数,类型R必须是由下式定义的输入范围std.range.isInputRange (so isInputRange!R必须是true),并且给定的谓词需要是一个二元函数,它使用给定的参数进行编译并返回一个可以隐式转换为的类型bool。如果模板约束条件的结果是false,那么模板将无法编译。这不仅可以保护您免受在 C++ 中模板无法使用给定参数进行编译时出现的令人讨厌的模板错误的影响,而且还可以使您可以根据模板约束重载模板。例如,还有另一个过载find这是

R1 find(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
if (isForwardRange!R1 && isForwardRange!R2
        && is(typeof(binaryFun!pred(haystack.front, needle.front)) : bool)
        && !isRandomAccessRange!R1)

它采用完全相同的参数,但其约束不同。因此,不同的类型使用同一模板化函数的不同重载,并且最佳实现find可用于每种类型。在 C++ 中没有办法干净地完成这类事情。只要稍微熟悉一下典型模板约束中使用的函数和模板,D 中的模板约束就相当容易阅读,而您需要在 C++ 中进行一些非常复杂的模板元编程才能尝试这样的事情,而普通程序员却做不到这一点都能够理解,更不用说自己亲自去做了。 Boost 就是一个典型的例子。它做了一些令人惊奇的事情,但它非常复杂。

static if进一步改善情况。就像模板约束一样,任何可以在编译时评估的条件都可以与它一起使用。例如

static if(isIntegral!T)
{
    //...
}
else static if(isFloatingPoint!T)
{
    //...
}
else static if(isSomeString!T)
{
    //...
}
else static if(isDynamicArray!T)
{
    //...
}
else
{
    //...
}

哪个分支被编译取决于哪个条件首先评估为true。因此,在模板中,您可以根据模板实例化的类型或基于可以在编译时评估的任何其他内容来专门化其实现的各个部分。例如,core.time uses

static if(is(typeof(clock_gettime)))

根据系统是否提供不同的方式编译代码clock_gettime或不(如果clock_gettime在那里,它使用它,否则它使用gettimeofday).

我见过的 D 对模板进行改进的最明显的例子可能是我的团队在工作中在 C++ 中遇到的一个问题。我们需要根据给定的类型是否派生自特定基类来以不同的方式实例化模板。我们最终使用了基于的解决方案这个堆栈溢出问题 https://stackoverflow.com/questions/2631585/c-how-to-require-that-one-template-type-is-derived-from-the-other。它有效,但仅测试一种类型是否派生于另一种类型是相当复杂的。

然而,在 D 中,您所要做的就是使用:操作员。例如

auto func(T : U)(T val) {...}

If T可以隐式转换为U(就像如果T源自U), then func将编译,而如果T不能隐式转换为U,那么就不会了。That简单的改进甚至可以使基本的模板专业化变得更加强大(即使没有模板约束或static if).

就我个人而言,除了容器和偶尔使用的函数之外,我很少在 C++ 中使用模板<algorithm>,因为它们使用起来非常痛苦。它们会导致丑陋的错误,并且很难做任何花哨的事情。要完成任何稍微复杂的事情,您都需要非常熟练地使用模板和模板元编程。不过,有了 D 中的模板,它非常简单,我一直在使用它们。这些错误更容易理解和处理(尽管它们仍然比非模板化函数通常出现的错误更糟糕),而且我不必弄清楚如何通过花哨的元编程强制语言执行我想要的操作。

C++ 没有理由不能获得 D 所拥有的大部分能力(如果它们能够解决这些问题,C++ 概念将会有所帮助),但直到它们添加了类似于模板约束和构造的基本条件编译和static if对于 C++,C++ 模板在易用性和功能方面无法与 D 模板相比。

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

C++ 和 D 中的元编程 的相关文章

随机推荐

  • 类内递归

    我试图在类语句中放置一个递归公式 class SomeNode def init self a leng len a half leng 2 self firstnode a 0 0 self child1 SomeNode a i for
  • 从外部连接到在 docker 容器内运行的服务

    我有一个服务在 docker 容器 本地机器 中运行 我可以在 Ambari 服务配置中看到服务 URL 现在我想使用本地开发环境连接到该服务 我发现我可以连接到容器内的该 URL 但是当我在本地外部使用该 URL 时 连接被拒绝 Caus
  • 为什么 vector 不是 STL 容器?

    Scott Meyers 的书第 18 条有效的 STL 改进标准模板库使用的 50 种具体方法说要避免vector
  • 专门化主模板时,更专门化意味着什么?

    C 模板特化规则中提到的特化必须比主模板更加特化 下面的 1 代码片段会导致编译错误 这表明第二行并不更专业 但最后一个片段 2 的工作看起来非常接近 1 两个代码片段都是专门的int N as 0 那么为什么第一个片段被抱怨为 不更专业
  • spect.getmembers() 与 __dict__.items() 与 dir()

    谁能用足够的例子向我解释黑白有什么区别 gt gt gt import inspect gt gt gt inspect getmembers 1 and gt gt gt type 1 dict items and gt gt gt di
  • 创建 SwiftUI 侧边栏

    我想使用 SwiftUI 构建一个非常简单的 iOS 14 侧边栏 设置很简单 我有三个视图HomeView LibraryView and SettingsView和代表每个屏幕的枚举 enum Screen Hashable case
  • jquery blockUI 判断页面或特定元素是否被阻止

    有没有办法判断 blockUI 是否有效已被调用但 unblockUI 尚未被调用 理想情况下 这应该能够阻止整个页面和特定元素 我希望它能像这样工作 gt blockUI gt isBlockUI gt gt true gt unbloc
  • HTML5 文档中的多个

    使用多个可以吗
  • WPF 网格不显示滚动条

    在 NET 3 5 中 我在窗口中有一个网格 我正在用按钮填充这个网格 当按钮填满网格并消失时 网格不会显示滚动条 我已将网格垂直滚动设置为可见 但它仍然不显示
  • 如何围绕特定点来回旋转物体?

    我正在使用 Raphael JS 尝试围绕中心点下方的点旋转图像形状 如何才能做到这一点 我已经尝试过以下方法 但它不起作用 var playBBox playButtonRef getBBox var xPos playBBox x pl
  • Spring Boot - 从依赖 jar 加载 application.properties/yml

    我有一个 Spring Boot 应用程序 我想按特定顺序将值注入到 ConfigurationProperties bean 中 例如 ConfigurationProperties myproperties class MyProper
  • 获取资源管理器窗口排序的字段

    我想知道是否有办法知道 Windows 资源管理器窗口中的文件是如何排序的 有点像窗口的 ORDER BY 子句 示例 名称升序 或 修改日期降序 这个问题不是关于 Windows 的名称排序算法 而是关于特定打开的 Windows 资源管
  • RVO(返回值优化)适用于所有对象吗?

    Is RVO 返回值优化 http en wikipedia org wiki Return value optimization 保证或适用于 C 编译器 特别是 GCC 中的所有对象和情况 如果答案是 否 那么类 对象的这种优化的条件是
  • 将命令行参数传递给随 Poetry 安装的 Python 脚本

    诗歌文档 https python poetry org docs pyproject scripts表示脚本部分可用于在安装包时安装脚本或可执行文件 但它没有显示任何如何将参数传递给脚本的示例 您如何才能接收argparse函数中的参数
  • IntelliJ JDK 16 抢先体验 - 有成功吗?工具.jar

    有没有人使用 JDK 16 取得过成功 https jdk java net 16 https jdk java net 16 使用 IntelliJ 进行早期访问构建 我能够使用 JDK 15 早期访问版本 但是当我尝试 JDK 16 时
  • 删除一项内的内容时在行上方创建神秘空间

    我有一个包含一些项目的网格 当我单击任何项 目时 我会将该项目的内容移动到模式中 该模式效果很好 但是当我从项目中删除内容时 项目上方会出现一个空格 我知道解决这个问题的方法可能是使用弹性盒 它工作得很好 但我想了解这里发生了什么 这里可能
  • CSS3 高度 100%

    我不知道如何问 写这个 所以请随时更新名称或指出正确的问题 标题 我正在设计一个跨 html5 css3 网站 并试图使其在每个 常见 浏览器上看起来都相同 这就是我所拥有的 http www pojotlan com example1 h
  • ProgressBars 和 Espresso

    当我在运行一些浓缩咖啡测试时显示的布局中有一个进度条时 然后我遇到 Caused by android support test espresso AppNotIdleException Looped for 1670 iterations
  • 在调试之前尝试启动带有任务的服务器时出现“无法跟踪指定的任务”

    我的调试配置如下launch json type node request attach preLaunchTask npm start name Attach port 9090 这是定义在中的任务tasks json type npm
  • C++ 和 D 中的元编程

    C 中的模板机制只是意外地对模板元编程有用 另一方面 D 是专门为促进这一点而设计的 显然它更容易理解 或者我听说过 我没有使用 D 的经验 但我很好奇 当涉及到模板元编程时 在 D 中可以做什么而在 C 中不能做什么 在 D 中帮助模板元