簡介
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:
與語法限制相反,指定有意義語義的能力是真正的概念的決定性特征。