专栏首页C++核心准则原文翻译C++20新特性简介-Concepts

C++20新特性简介-Concepts

本文根据作者个人理解介绍C++20标准中引入的新概念:Concept

强大的泛型编程

基本上从C++语言出现开始,泛型编程就是C++的重要组成部分之一。使用编程,可以在实现一次编程多次使用的同时,又不会损失精度。简直就是完美。例如我们可以实现一个简单的、可以处理多种数据类型的模板加法函数:

template<typename T>
T add(T in1, T in2)
{
    return in1 + in2;
}

有了这个模板函数之后,可以使用它处理各种数据类型。例如:

std::cout << add(1, 3) << std::endl;
std::cout << add(2.0, 4.0) << std::endl;

编译器可以根据输入数据的类型自动生成下面的函数(可能不严密),从而避免代码冗余。

int add(int in1, int in2)
{
    return in1 + in2;
}
double add(double in1, double in2)
{
    return in1 + in2;
}

泛型编程在实现和算法相关的处理时特别有用。C++标准库中的容器,算法等功能库中,大量使用的泛型编程。

困难的泛型编程

如果只是使用C++标准库中的容器、算法的话,一般不会遇到太大的问题。一旦自己要设计、开发和调试模板库,就会立即遭遇泛型编程的首要难题:问题的判断、解决都很困难。作者本人就有过由于实在难于调试,因此先改回一般函数,调试完成后再转成模板方式的经历。例如我们另外设计一个复数类:

class Complex
{
public:
    double real = 0;
    double imaginary = 0;
};

同样对它调用add函数:

std::cout << add(Complex{ 1,2 }, Complex{ 2,-3 });

编译之后,开发环境显示如下:

信息的内容主要有:

出错的位置是代码第22行。由于这个模板函数已经可以用于整数和双精度数,错误的原因不在模板函数本身,而是在调用模板时使用实际数据Complex。但问题是错误信息并没有提示是哪个调用出的问题。

另外,错误信息显示没有匹配的+操作符,这是真正的原因。但是接下来Complex没有从各种类继承等附注信息就只有添乱了。作者相信只要使用过泛型编程的程序员都会有过类似的经历。

对策很简单,重载一个针对Complex的+运算符就行了。

C++20新特性之Concept

很快就会正式发布的C++20引入了一个新特性-Concept。简单讲就是描述模板参数的特性和要求。例如对于add模板函数来讲,我们要求模板参数是可以执行加法运算的,这是可以定义下面的Concept:

template<typename T>
concept Addable = requires (T obj) {{obj + obj}->std::same_as<T>;};

concept Addable声明名为Addable的概念。

requires用来描述各种需求,它的参数有点像函数的参数定义,参数的类型可以是模板参数(例如T),也可以是已经定义的其他类型。参数名obj的作用类似变量,会在需求描述中使用。

{obj+obj}描述加法运算,它的涵义是T类型的对象obj需要支持加法运算,而花括号后面的->所指的是花括号中的运算结果应该满足的条件,这里使用了标准库中的same_as约束,要求结果类型和T是一样的。

简单说来,就是T类型应该支持加法运算,而且结果类型还是T。

定义Concept之后,模板函数这样写:

template<Addable T>
T add(T in1, T in2)
{
    return in1 + in2;
}

唯一的变化就是将typename T改成了Addable T,表明这个T是要符合Addable概念的。引入的Concept之后,同样的问题,显示的错误信息完全不同:

出错的位置从模板函数内部变成了调用模板函数的代码(58行)。软件规模变大之后,快速定位引发问题的位置特别重要。

错误提示也很清晰,都是说没有满足特定的约束条件。没有任何干扰信息。

扩展阅读

目前,关于Concept的资料还很少,例如:

https://zh.cppreference.com/w/cpp/language/constraints

https://www.modernescpp.com/index.php/c-20-concepts-the-details

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/n4849.pdf

读者可以在阅读本文之后去理解这些资料。

体验Concepts

虽然C++20还没有正式发布,但是无论GCC还是VisutalStudio都对C++20提供了一定程度的支持。体验Concept的方法请参照作者的以下文章:

用VisualStudio2019预览版体验C++20新功能

在Ubuntu20.04环境中构建C++20开发环境(GCC11)

无论哪种情况都需要设定C++标准为C++2a以上这一点不要忘了。


觉得本文有帮助?请分享给更多人。

关注微信公众号【面向对象思考】轻松学习每一天!

面向对象开发,面向对象思考!

本文分享自微信公众号 - 面向对象思考(OOThinkingDalian),作者:面向对象思考

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-05-25

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • C++核心准则​CPL.2:如果你必须使用C,使用C和C++的共同子集,并且使用C++编译器编译C代码

    CPL.2: If you must use C, use the common subset of C and C++, and compile the C ...

    面向对象思考
  • C++核心准则边译边学-序言

    C++核心准则(C++ Core Guidelines)是由C++语言两位大神级的人物发表的有关C++语言编程的指导性文件,目前还处于不断修改和完善的过程中。从...

    面向对象思考
  • C++核心准则CP.110:不要自已为初始化编写双重检查锁定代码

    Since C++11, static local variables are now initialized in a thread-safe way. Wh...

    面向对象思考
  • windows中使用Git如何解决文件冲突?

    假设在合并Pull Request到我们的主分支之前,想对要合并的新分支添加修改,该如何做呢? 答:只需到回到windows中对新分支中的文件进行修改再保存...

    黑泽君
  • 更高效的SSL证书监控方案

    上篇文章"简单脚本监控SSL证书,到期告警提醒"发布之后,不少朋友说项目少的情况还好,在zabbix中手动添加监控项和触发器就可以,但项目多的时候,一条一条添加...

    李俊鹏
  • 阿里缩招(从3000人大幅砍到400人)降薪,互联网寒冬要来了吗?

    近日阿里巴巴校园招聘发布了一则最新的通知“我们非常抱歉地通知:由于集团人才战略调整,阿里巴巴2016校招名额确定将要缩减,各岗位将执行更加严格的“择优录取” 标...

    华章科技
  • PS色调均化滤镜的快捷实现(C#源代码)。

      photoshop色调均化功能通常是在进行修片处理前期比较常用的功能之一,其对扩展图像的对比度,增强视觉效果有一定的作用。在很多课本或者文章中,也称这种处理...

    用户1138785
  • C盘空间满了怎么办?

    简单并不简单
  • 用geotools自己写WMS服务

    本文讲述如何结合geotools写一个类似于WMS的地图服务,并实现在OL4中的调用展示。

    lzugis
  • jQuery选择器 和用jQuery 实现 Tab 切换效果(1)

    通过类数组下标的获取方式或者get方法获取指定index的DOM对象,也就是我们说的jQuery对象转DOM对象

    bamboo

扫码关注云+社区

领取腾讯云代金券