C++ concept的概念和使用

这篇具有很好参考价值的文章主要介绍了C++ concept的概念和使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

C++ concept的概念和使用

concept 这套语法优化了模板编程,替代了原来的SFINAE编程模式,通过给模板类参数加入限制条件,使得代码可读性更强、编译更快、错误提示更容易理解。

SFINAE编程模式

SFINAE 是"Substitution Failure Is Not An Error"的简称。

模板实例化时类型推演失败不会报错,而是当成一个语言特性。利用模板通用定义和模板特化,对于不同的模板参数给予不同的实现。

int T::* 表示指向T的成员的指针。

Keywords

concept

定义类似模板的东西,在requires 中使用。

template <class T>
concept integral = std::is_integral_v<T>;

requires

有以下作用:

用于定义concept。

template <typename T>
concept ILabel = requires(T v)
{
    {v.buildHtml()} -> std::convertible_to<std::string>;
};

用于为模板施加限制。

template <typename T>
requires CONDITION
void DoSomething(T param) { }

另一种写法

template <typename T>
void DoSomething(T param) requires CONDITION
{ 
}

代码示例

我自己的例子
template <typename T>
concept should_be_float = std::is_floating_point_v<T>;

template <typename T> requires should_be_float<T>
T add(T a, T b) { return a + b; }


void concept_test()
{
    auto r = add(1.2, 3.3);
    auto r2 = add(1, 2);  // 编译不过
}
STL的例子
template <class _LTy, class _RTy>
concept assignable_from = is_lvalue_reference_v<_LTy>
    && common_reference_with<const remove_reference_t<_LTy>&, const remove_reference_t<_RTy>&>
    && requires(_LTy _Left, _RTy&& _Right) {
        { _Left = static_cast<_RTy&&>(_Right) } -> same_as<_LTy>;
    };

concepts library

<concepts>头文件中定义了一些预定义的concept。

  • same_as

  • derived_from

  • convertible_to

  • common_reference_with

  • common_with

  • integral

  • signed_integral

  • unsigned_integral

  • floating_point

  • assignable_from

  • swappable / swappable_with

  • destructible

  • constructible_from

  • default_initializable

  • move_constructible

  • copy_constructible

  • boolean-testable

  • equality_comparable

  • movable

  • copyable

  • semiregulasr

  • regular

  • invocable

  • predicate

  • relation

  • equivalence_relation

  • strict_weak_order

语法糖

auto 关键字

省去template,将

template <typename T>
auto foo(T p) {}

改写为:

auto foo(auto p) {} 

可以极为化简模板函数代码,比如:

auto foo2(auto a, auto b)
{
    return a + b;
}

int main()
{
    std::cout << foo2(1.2, 2) << std::endl;
    std::cout << foo2(1, 2) << std::endl;
    std::cout << foo2(1.2, 1.6) << std::endl;
}

与concepts合用

void print3(const std::ranges::range auto& c)
{
    for (auto && elem : c)
    {
        std::cout << elem << ", ";
    }
    std::cout << std::endl;
}
int main()
{
    std::vector<int> c{ 1,2,4,5,12,23,88,23, 17 };
    print3(c);
}

template + concept 更加可读的写法

用concept名字替代关键字 template 或者 class

template <std::integral T>
auto sum(const std::vedctor<T>& vec)
{
    // return ...
}

还可以跟模板可变参数合用。

template <typename T>
concept number = std::integral<T> || std::floating_point<T>;

template <number ...TArgs>
auto sum_all(TArgs ...args)
{
    return (... + args);
}

int main()
{
    std::cout << sum_all(1, 2, 3) << std::endl;
    std::cout << sum_all(1, 2.2, 3) << std::endl;
    std::cout << sum_all(1.1, 2.2, 3.3) << std::endl;
}

结合auto关键字,能有更简洁的写法。

template <typename T>
concept number = std::integral<T> || std::floating_point<T>;

auto sum_all(const number auto & ...args)
{
    return (... + args);
}

int main()
{
    std::cout << sum_all(1, 2, 3) << std::endl;
    std::cout << sum_all(1, 2.2, 3) << std::endl;
    std::cout << sum_all(1.1, 2.2, 3.3) << std::endl;
}

鸭子类型

利用concepts语言特性,得到类似Ruby语言那样的鸭子类型(duck typing)和mixin特性(例如Ruby的Enumerable)。

鸭子类型是指“如果一个动物走起来像鸭子,叫起来也像鸭子,那么它就是鸭子”。也就是说不关心一个类型是不是继承于某个基类,而是看类型是否实现了某些方法(在concepts中可以扩展成某些成员变量、成员类型、返回特定类型的方法等等)。基于鸭子类型实现了mixin,mixin是指非侵入式地为某个鸭子类型的所有类型赋予某方面的能力。例如Ruby的Enumerable对所有实现了“取值”和“下一个”的方法的类型,提供了一系列迭代器相关的方法(first, last, find 等等)。鸭子类型的好处是在于其“非侵入式”。

用concept定义一个鸭子类型。

template <typename T>
concept IClock = requires(T c) {
    c.start();
    c.stop();
    c.getTime();
};

void foo3(IClock auto& clock)
{
    clock.start();
    clock.stop();
}

其他

尾部返回类型

引入尾部返回类型的背后原因是模板函数根据模板参数确定返回类型。

template<typename A, typename B>
??? multiply(A a, B b) { return a*b}

C++编译器是从左往右处理代码(就是lexical order),当扫描到返回类型的时候尚未扫描到模板参数a和b,因此无法使用decltype(a*b)这个东西。Trailing Return Types解决这个问题的方法如下代码所示:

template<typename A, typename B>
auto multiply(A a, B b) -> decltype(a*b) { return a * b; }

其他原因是:文章来源地址https://www.toymoban.com/news/detail-706550.html

  1. 跟lambda定义的风格一样;
  2. 名字比返回类型重要,应该在前面;
  3. 与数学上函数定义(R -> R)一致。

References

  1. [C++ Trailing Return Types ‐ Daniel Sieger](https://www.danielsieger.com/blog/2022/01/28/cpp-trailing-return-types.html#:~:text=Trailing return types are an alternative syntax introduced,return type after the function name and parameters%3A)
  2. C++20 Concepts - a Quick Introduction - C++ Stories (cppstories.com)
  3. Concepts library (since C++20) - cppreference.com
  4. Predefined C++20 Concepts: Callables - C++ Stories (cppstories.com)
  5. Requires-expression | Andrzej’s C++ blog (wordpress.com)

到了这里,关于C++ concept的概念和使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 英语写作中“概念”concept 、notion、idea的用法

    一、概念concept、notion 是同义词,一般可以互换,例如: The notion/concept of public keys is introduced in the paper “New Direction of Cryptography” half a century ago. Public keys have been widely accepted as a cryptographic concept/notion nowadays.(公钥的概念在半个世纪前的一篇文章“密码学的新方向”中提

    2024年04月09日
    浏览(25)
  • AI 作画《Concept Art概念艺术》| 用stable diffusion生成

    前言 “Concept Art”是一个艺术门类,即所谓“概念艺术”、“概念设计”,也称为“初步设计”。一般常见于影视或游戏设计中,服务产品最初的视觉效果,是游戏或影片的核心工作内容之一。 下面让我们使用当前很火的扩散模型stable diffusion,生成一些概念艺术作品!看看

    2024年02月11日
    浏览(53)
  • C++ 模板 using, Concept

     用IteratorMemberFunctionT(T::begin)从T中获取成员函数的函数指针 使用decltype获取类型,判断该类型是否为一个成员函数,不包含 begin 就会违反这个约束

    2024年02月11日
    浏览(25)
  • 【VisualStudio】使用 C++ 语言开发 Qt 环境配置教程

    知识不是单独的,一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏:Visual Studio。 先上一张效果图,具体步骤主要分为以下三步。 这一步不再赘述,注意一定要安装 C++ 语言。 可以参考这个教程 Visual Studio 2022安装与使用教程。 这一步也不再赘述,网上搜索教

    2024年02月10日
    浏览(63)
  • NXP恩智浦 S32G电源管理芯片 VR5510 安全概念 Safety Concept (万字长文详解,配21张彩图)

    本应用笔记描述了与S32G处理器和VR5510 PMIC相关的安全概念。该文档涵盖了S32G和VR5510的安全功能以及它们如何相互作用,以确保对ASIL D安全完整性级别进行系统级覆盖。 本应用笔记介绍了针对S32G3应用的VR5510和PF5300 PMIC解决方案。所有具体的修改和更新都在第4.2节中描述。 2.

    2024年04月28日
    浏览(25)
  • Java Polymorphism Concept

    这个多态看中文确实有点费解,多态的英文是Polymorphism,它的翻译含义是: n. 多态性 (可以看出是比较宽泛的) n. 多型现象 从翻译也看不出啥, 我举一个生活中的例子来引入多态: 生活中有很多常见的物体具有多态性。例如,一张纸可以用来写字、画画,也可以用来包裹东

    2024年02月12日
    浏览(98)
  • Java Polymorphism Concept —— OOP

    这个多态看中文确实有点费解,多态的英文是Polymorphism,它的翻译含义是: n. 多态性 (可以看出是比较宽泛的) n. 多型现象 从翻译也看不出啥, 我举一个生活中的例子来引入多态: 生活中有很多常见的物体具有多态性。例如,一张纸可以用来写字、画画,也可以用来包裹东

    2024年02月12日
    浏览(34)
  • 【VisualStudio】基于 Visual Studio 使用 C++ 语言开发 Qt 环境配置教程

    知识不是单独的,一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏:Visual Studio。 先上一张效果图,具体步骤主要分为以下三步。 这一步不再赘述,注意一定要安装 C++ 语言。 可以参考这个教程 Visual Studio 2022安装与使用教程。 这一步也不再赘述,网上搜索教

    2024年02月15日
    浏览(50)
  • 【Visual Studio】使用 C++ 语言,配合 Qt,开发了一个串口通信界面

    知识不是单独的,一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏:Visual Studio。 我要使用的功能比较简单,主要包含扫描串口、打开串口、发送数据、接收数据、暂停按钮、停止按钮,因此接下里将围绕这几个功能依次更新。 我的工程项目名字叫 “GUI”。

    2024年02月11日
    浏览(57)
  • 【Visual Studio】报错 C2653,使用 C++ 语言,配合 Qt 开发串口通信界面

    知识不是单独的,一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏:Visual Studio。 这个 Bug 是我做这个工程时遇到的:【Visual Studio】Qt 的实时绘图曲线功能,使用 C++ 语言,配合 Qt 开发串口通信界面。 使用 C++ 语言,配合 Qt 开发串口通信界面,在添加 Widget 做

    2024年02月11日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包