C++ 概念与 static_assert

2024-01-12

C++ 概念中有哪些新内容?根据我的理解,它们在功能上等同于使用static_assert,但以一种“好的”方式意味着编译器错误将更具可读性(正如 Bjarne Stroustup 所说,您不会得到 10 个页面或错误,而只会得到一个)。

基本上,你用概念能做的一切是否也可以用它来实现?static_assert?

我有什么遗漏的吗?


tl;dr

相比static_asserts,概念更强大,因为:

  • 它们可以为您提供良好的诊断,这是您无法轻易实现的static_asserts
  • 它们可以让您轻松重载模板函数,而无需std::enable_if(这是不可能的,只有static_asserts)
  • 它们允许您定义静态接口并重用它们而不会丢失诊断(需要多个static_asserts在每个函数中)
  • 它们可以让你更好地表达你的意图并提高可读性(这是模板的一个大问题)

这可以缓解以下问题:

  • 模板
  • 静态多态性
  • 超载

并成为有趣范例的构建块。


什么是概念?

概念表示满足某些要求的类型的“类”(不是 C++ 术语,而是作为“组”)。作为示例,您可以看到Swappable http://en.cppreference.com/w/cpp/concept/Swappable概念表达了以下类型的集合:

  • 允许呼叫std::swap

你可以很容易地看到,例如,std::string, std::vector, std::deque, int等等...满足这个要求,因此可以在如下函数中互换使用:

template<typename Swappable>
void func(const Swappable& a, const Swappable& b) {
    std::swap(a, b);
}

概念一直存在于C++中 http://en.cppreference.com/w/cpp/concept,在(可能不久)将来添加的实际功能将只允许您用语言表达和强制执行它们。


更好的诊断

就更好的诊断而言,我们现在只能相信委员会。但他们“保证”的输出:

error: no matching function for call to 'sort(list<int>&)'
sort(l); 
      ^
note: template constraints not satisfied because 
note: `T' is not a/an `Sortable' type [with T = list<int>] since
note: `declval<T>()[n]' is not valid syntax

非常有前途。

确实,您可以使用以下方法获得类似的输出static_assert但这需要不同的static_assert每个函数都需要一个 s,这可能很快就会变得乏味。

举个例子,假设您必须执行以下要求的数量:Container http://en.cppreference.com/w/cpp/concept/Container2 个采用模板参数的函数中的概念;您需要在两个函数中复制它们:

template<typename C>
void func_a(...) {
    static_assert(...);
    static_assert(...);
    // ...
}

template<typename C>
void func_b(...) {
    static_assert(...);
    static_assert(...);
    // ...
}

否则,您将无法区分哪些要求未得到满足。

使用概念,您可以定义概念并通过简单地编写来强制执行它:

template<Container C>
void func_a(...);

template<Container C>
void func_b(...);

概念超载

引入的另一个重要功能是能够在模板约束上重载模板函数。是的,这也是可能的std::enable_if,但我们都知道这会变得多么丑陋。

举个例子,你可以有一个可以工作的函数Containers 并用一个恰好可以更好地工作的版本来重载它SequenceContainers:

template<Container C>
int func(C& c);

template<SequenceContainer C>
int func(C& c);

没有概念的替代方案是这样的:

template<typename T>
std::enable_if<
    Container<T>::value,
    int
> func(T& c);

template<typename T>
std::enable_if<
    SequenceContainer<T>::value,
    int
> func(T& c);

绝对更难看并且可能更容易出错。


更清晰的语法

正如您在上面的示例中所看到的,语法绝对更清晰,概念更直观。这可以减少表达约束所需的代码量并可以提高可读性。

如前所述,您实际上可以通过以下方式达到可接受的水平:

static_assert(Concept<T>::value);

但到那时你就会失去对不同事物的伟大诊断static_assert。有了概念,你就不需要这种权衡。


静态多态性

最后,概念与其他函数范例(例如 Haskell 中的类型类)有有趣的相似之处。例如,它们可用于定义静态接口.

例如,让我们考虑一下(臭名昭著的)游戏对象接口的经典方法:

struct Object {
    // …
    virtual update() = 0;
    virtual draw() = 0;
    virtual ~Object();
};

然后,假设你有一个多态std::vector您可以执行以下操作的派生对象:

for (auto& o : objects) { 
    o.update();
    o.draw();
}

很好,但是除非您想使用多重继承或基于实体组件的系统,否则您几乎只能为每个类提供一个可能的接口。

但如果你真的想要静态多态性(多态性不是that毕竟是动态的)你可以定义一个Object需要的概念update and draw成员函数(可能还有其他函数)。

那时你可以创建一个自由函数:

template<Object O>
void process(O& o) {
    o.update();
    o.draw();
}

之后,您可以根据其他要求为游戏对象定义另一个接口。这种方法的优点在于您可以开发任意数量的接口,而无需

  • 修改你的课程
  • 需要一个基类

它们都在编译时进行检查和强制执行。

这只是一个愚蠢的例子(而且是一个非常简单的例子),但概念确实为 C++ 中的模板打开了一个全新的世界。

如果您想了解更多信息,您可以读这篇好文章 http://bartoszmilewski.com/2010/11/29/understanding-c-concepts-through-haskell-type-classes/关于 C++ 概念与 Haskell 类型类。

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

C++ 概念与 static_assert 的相关文章

  • 为什么两个不同的 Base64 字符串的转换会返回相等的字节数组?

    我想知道为什么从 base64 字符串转换会为不同的字符串返回相同的字节数组 const string s1 dg const string s2 dq byte a1 Convert FromBase64String s1 byte a2
  • 在结构中使用 typedef 枚举并避免类型混合警告

    我正在使用 C99 我的编译器是 IAR Embedded workbench 但我认为这个问题对于其他一些编译器也有效 我有一个 typedef 枚举 其中包含一些项目 并且我向该新类型的结构添加了一个元素 typedef enum fo
  • 查找c中结构元素的偏移量

    struct a struct b int i float j x struct c int k float l y z 谁能解释一下如何找到偏移量int k这样我们就可以找到地址int i Use offsetof 找到从开始处的偏移量z
  • 使用实体框架模型输入安全密钥

    这是我今天的完美想法 Entity Framework 中的强类型 ID 动机 比较 ModelTypeA ID 和 ModelTypeB ID 总是 至少几乎 错误 为什么编译时不处理它 如果您使用每个请求示例 DbContext 那么很
  • 如何从 appsettings.json 文件中的对象数组读取值

    我的 appsettings json 文件 StudentBirthdays Anne 01 11 2000 Peter 29 07 2001 Jane 15 10 2001 John Not Mentioned 我有一个单独的配置类 p
  • 将 VSIX 功能添加到 C# 类库

    我有一个现有的单文件生成器 位于 C 类库中 如何将 VSIX 项目级功能添加到此项目 最终目标是编译我的类库项目并获得 VSIX 我实际上是在回答我自己的问题 这与Visual Studio 2017 中的单文件生成器更改 https s
  • 带动态元素的 WPF 启动屏幕。如何?

    我是 WPF 新手 我需要一些帮助 我有一个加载缓慢的 WPF 应用程序 因此我显示启动屏幕作为权宜之计 但是 我希望能够在每次运行时更改屏幕 并在文本区域中显示不同的引言 这是一个生产力应用程序 所以我将使用非愚蠢但激励性的引言 当然 如
  • 重载<<的返回值

    include
  • WCF 中 SOAP 消息的数字签名

    我在 4 0 中有一个 WCF 服务 我需要向 SOAP 响应添加数字签名 我不太确定实际上应该如何完成 我相信响应应该类似于下面的链接中显示的内容 https spaces internet2 edu display ISWG Signe
  • 使用 Bearer Token 访问 IdentityServer4 上受保护的 API

    我试图寻找此问题的解决方案 但尚未找到正确的搜索文本 我的问题是 如何配置我的 IdentityServer 以便它也可以接受 授权带有 BearerTokens 的 Api 请求 我已经配置并运行了 IdentityServer4 我还在
  • 如何设计以 char* 指针作为类成员变量的类?

    首先我想介绍一下我的情况 我写了一些类 将 char 指针作为私有类成员 而且这个项目有 GUI 所以当单击按钮时 某些函数可能会执行多次 这些类是设计的单班在项目中 但是其中的某些函数可以执行多次 然后我发现我的项目存在内存泄漏 所以我想
  • SolrNet连接说明

    为什么 SolrNet 连接的容器保持静态 这是一个非常大的错误 因为当我们在应用程序中向应用程序发送异步请求时 SolrNet 会表现异常 在 SolrNet 中如何避免这个问题 class P static void M string
  • 如何在整个 ASP .NET MVC 应用程序中需要授权

    我创建的应用程序中 除了启用登录的操作之外的每个操作都应该超出未登录用户的限制 我应该添加 Authorize 每个班级标题前的注释 像这儿 namespace WebApplication2 Controllers Authorize p
  • 控件的命名约定[重复]

    这个问题在这里已经有答案了 Microsoft 在其网站上提供了命名指南 here http msdn microsoft com en us library xzf533w0 VS 71 aspx 我还有 框架设计指南 一书 我找不到有关
  • 这些作业之间是否存在顺序点?

    以下代码中的两个赋值之间是否存在序列点 f f x 1 1 x 2 不 没有 在这种情况下 标准确实是含糊不清的 如果你想确认这一点 gcc 有这个非常酷的选项 Wsequence point在这种情况下 它会警告您该操作可能未定义
  • cmake 将标头包含到每个源文件中

    其实我有一个简单的问题 但找不到答案 也许你可以给我指一个副本 所以 问题是 是否可以告诉 cmake 指示编译器在每个源文件的开头自动包含一些头文件 这样就不需要放置 include foo h 了 谢谢 CMake 没有针对此特定用例的
  • C# 成员变量继承

    我对 C 有点陌生 但我在编程方面有相当广泛的背景 我想做的事情 为游戏定义不同的 MapTiles 我已经像这样定义了 MapTile 基类 public class MapTile public Texture2D texture pu
  • 混合 ExecutionContext.SuppressFlow 和任务时 AsyncLocal.Value 出现意外值

    在应用程序中 由于 AsyncLocal 的错误 意外值 我遇到了奇怪的行为 尽管我抑制了执行上下文的流程 但 AsyncLocal Value 属性有时不会在新生成的任务的执行范围内重置 下面我创建了一个最小的可重现示例来演示该问题 pr
  • 是否可以在 .NET Core 中将 gRPC 与 HTTP/1.1 结合使用?

    我有两个网络服务 gRPC 客户端和 gRPC 服务器 服务器是用 NET Core编写的 然而 客户端是托管在 IIS 8 5 上的 NET Framework 4 7 2 Web 应用程序 所以它只支持HTTP 1 1 https le
  • 使用.NET技术录制屏幕视频[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有一种方法可以使用 NET 技术来录制屏幕 无论是桌面还是窗口 我的目标是免费的 我喜欢小型 低

随机推荐