简介
concept是C++ 20中的新语法,他是对泛型具有的行为的一种约束。
理论上,不使用concept编译器也会在解析模板的时候检查泛型的行为,但引入concept后可以在代码中手动增加约束,提高程序的健壮性和编译速度。
快速上手
#include <iostream>
using namespace std;
// 定义Addable概念,要求类型可以进行加运算
template <typename T>
concept Addable = requires (T x) {
x + x;
};
// 要求类型T具有Addable特性
template <typename T>
requires Addable<T>
void f(T x)
{
return x + x + x;
}
int main()
{
cout << f<int>(10) << endl; //通过
cout << f<vector>(vector()) << endl; // 编译不通过
return 0;
}
concept和requires子句
可以像定义函数一样定义requires子句,编译时会检查类型T是否满足子句内所有语句的语法
template <typename T>
concept Addable = requires (T x) {
x + x;
};
concept实际上是一个require子句的标记符号,以下代码是等效的
template <typename T>
concept Addable = requires (T x) {
x + x;
};
template <typename T>
requires Addable<T>
void f(T x)
{
return x + x + x;
}
template <typename T>
requires (T x) { x + x; }
void f(T x)
{
return x + x + x;
}
标准库中的concept
对于常见的concept,C++标准库提供了,如整数概念
template <typename T>
concept Integer = std::is_integral<T>::value;
concept的组合
可以使用 &&
和 ||
来组合两个概念,正如字面意思
#include <iostream>
using namespace std;
// 加法
template <typename T>
concept Addable = requires (T x) {
x + x;
};
// 小于等于
template <typename T>
concept Comparable = requires (T x) {
x <= 2;
};
template <typename T>
requires Addable<T> && Comparable<T> //同时使用Addable和Comparable
T fib(T x)
{
return x<=2? x : fib(x-1)+fib(x-2);
}
int main()
{
cout << fib<int>(20) << endl;
return 0;
}
基本concept
基本(atomic)concept是一个形如 bool Concept<T>()
的模板, 它接收一个泛型T
,返回true
或false
。
require Concept<T>
实际上是检查经过模板解析后,Concept<T>
是true
(编译通过),还是false
(编译不通过)
例
template<typename T>
constexpr bool TestFn()
{
T t{};
if(...) {
return true;
}
else
{
return false;
}
}
template<typename T>
requires (TestFn<T>())
concept不是为了给代码增加障碍
尽管上面的例子中的Addable看起来就是在为传参增加一道门槛,但Addable这种concept不是ISO C++制定concept这个语法的初衷,甚至是典型的违背初衷的concept:
与语法限制相反,指定有意义语义的能力是真正的概念的决定性特征。