C++程序员应了解的那些事(81) concept for C++20

本文介绍了C++20中的新特性——概念(Concepts),它允许开发者更精确地定义模板参数的限制,避免模板实例化时产生错误。通过示例展示了使用概念定义函数的方式,包括Bjarne Stroustrup推崇的样式和其他三种常见形式,并解释了如何利用概念进行函数重载。此外,文章还提到了概念在编译错误提示方面的改进,使得错误信息更加清晰明了。
摘要由CSDN通过智能技术生成

       concept其实已经不是什么新东西了,属于C++里面喊了无数次狼来了的东东,直到C++20才正式进入。其实也难怪,毕竟C++是一个非常庞大的机器,牵一发而动全身,需要将各种边边角角的情况都考虑严谨了,再加入标准才更靠谱。

       concept对于普通开发者来说,最明显的作用就是在模板参数不满足鸭子类型的约束时编译器不再给出几千行奇奇怪怪的错误。当然还有其它的作用,比如说concepts可以用来实现函数的重载、新的concepts可以基于已有的concepts定义从而进行扩展等等。

       标准库已经定义了一些常用的concepts了,位于头文件<concepts>中。concept的使用和定义都很简单,本篇只讲使用,为了讲后面关于使用的例子先定义一个最简单的cocept。

template<typename T>
concept Integral = std::is_integral<T>::value;

        C++20引入了concept和requires关键字,相关功能的使用方法至少有四种,似乎很多,但是只要看一遍即使记不住下次看到别人写的也能看懂。我们用上面定义好的Integral来定义一个最简单的Add函数,以这个函数为例来说明各种不同的用法格式。

        第一种是Bjarne Stroustrup最喜欢的,他甚至觉得剩下的几种用法都是多余的,但是众口难调,投票决定,很多东西他也做不了主。来看看这种用法吧,就是用了一个多余的auto关键字,来说明auto前面的Integral是一个concept:

Integral auto Add(Integral auto a, Integral auto b)
{
    return a + b;
}
// 可以用新的格式:Integral auto c = Add(10, 3)来调用,
// 当然也可以用以前的调用方法:int c = Add(10, 3)

        再来看第二种,在template声明以后紧接着用requires关键字说明模板参数需要满足的concept:

template<typename T> 
requires Integral<T>
T Add(T a, T b)
{
    return a + b;
}
// 这种用法不必对函数声明中的每个T都写成长长的Integral auto,
// 当函数参数较多时明显比第一种要好,所以Bjarne Stroustrup也不见得是对的,毕竟人都有偏见。

        继续看第三种,这种和第二种的区别就是将requires Integral<T>挪动了位置,放在了函数声明的后面,效果是一样的:

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

       第四种是省略了requires关键字,直接将concept的名字放入到模板参数前面,同时也省去了平常模板声明用的typename或class,这种方法最直观,如下:

template<Integral T>
T Add(T a, T b)
{
    return a + b;
}

        其实以前在concept-ts中还有第五种比较奇葩的语法,貌似在C++20中已经删掉了,但是在gcc中仍然可以编译通过(毕竟gcc是第一个实现concept-ts的编译器),如下: 

Integral{T}
T Add(T a, T b)
{
    return a + b;
}

       因为上面已经指定了Add函数必须用Inetegral的参数才能调用,用其它的类型就会编译出错,编译器应该会给出明确的错误。用double类型的参数来调用一下看看:

auto c = Add(10.3, 5.2);
// 编译器给出类似这样的错误:
// error: use of function 'T Add(T, T) [with T = double]' with unsatisfied constraints

       concept还可用于函数的重载,假设我再加上一个普通的Add函数,上面的代码可以编译通过,普通的Add函数就和C++20之前的函数一样:

template<class T>
T Add(T a, T b)
{
    return a + b;
}

      加了这个 函数以后,不满足Integral的参数就会调用这个函数,而满足Integral的参数会调用之前用concept定义的函数,编译器一如既往地选择最匹配的函数。

 

参考:

C++20 概念(concepts)入门

concept for C++20用法简介

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值