CTTCG 附录 E Concept
定义和使用 concept
下面演示了几种 C++20 支持的定义 concept 的方式,每一条约束都是以下之一,然后用分号结尾:
- 类型
- 表达式
- { 表达式 } noexcept -> 检查返回类型是否满足其他约束(这个 noexcept 可以不要)
- 引入其他
requires
表达式
template <typename T>
concept StringConcept = requires(T t) {
typename T::iterator; // 1. 检查类型存在性
t.data(); // 2. 检查表达式合法性
// 3. 将表达式作为 concept 的第一个参数,要求 concept 成立(额外参数从第二个参数起放置)
{ t.c_str() } -> std::same_as<char const *>;
// 4. 用 requires 语句引入子条件
requires std::is_pointer_v<decltype(t.data())>;
// 5. 除了 requires 体之外还能用其他编译期常量表达式做约束
} && (sizeof(T) > 8) && !std::is_aggregate_v<T>;
template<StringConcept Str>
void takeString(Str const &s) { }
int main() {
takeString(std::string{"hello"});
}
在模板中加上 requires
条件则相对比较简单。只需要在 模板参数后,函数返回值前面,或者 函数体前面 加上 requires
约束。requires
约束能使用一般的条件表达式,也能把 concept 当成 type trait 使用。比如:
template <typename T>
requires HasPlus<T>
int f(T p)
{}
template <typename T>
int g(T p)
requires HasPlus<T>
{}
// 注意 requires 约束的位置比较灵活