concepts是c++20引入的编译期约束声明,用于限定模板参数必须满足的要求(如可比较、可构造等),而非运行时检查、宏或typedef语法糖;未满足时直接报明确错误,避免晦涩模板展开失败。

concepts 是什么,不是什么
它不是运行时检查,也不是宏或 typedef 的语法糖;它是编译期的约束声明,让模板参数必须满足一组要求(比如可比较、可构造、有某个成员函数)。没满足就直接报错,而不是等到实例化出一堆晦涩的模板展开错误。
常见错误现象:error: no matching function for call to ... 一长串模板推导失败,根本看不出哪条约束没过。用了 concept 后,错误会聚焦在“T 不满足 Sortable:缺少 operator”这类明确提示。
怎么写一个基础 concept
用 template<typename t></typename> + concept 关键字 + requires 块,里面放约束表达式:
template<typename t>
concept LessThanComparable = requires(T a, T b) {
{ a std::convertible_to<bool>;
};</bool></typename>
说明:
-
requires块里是“能写出这些代码且类型合法”,不是“执行结果为真” -
{ a std::convertible_to<bool></bool>表示表达式存在,且返回值能隐式转成bool;不加箭头只检查表达式存在,但不验返回类型 - 别漏掉
std::convertible_to这类标准概念——它本身也是 concept,不是类型 trait - 参数名(如
a,b)只是占位符,不参与求值,也不需要定义
怎么在模板中使用 concept 约束
三种写法等价,但语义和错误提示质量不同:
- 简写形式(推荐):
template<lessthancomparable t> void sort(T* begin, T* end);</lessthancomparable> - requires 子句:
template<typename t> void sort(T* begin, T* end) requires LessThanComparable<t>;</t></typename> - 约束的函数模板参数:
void sort(LessThanComparable auto* begin, LessThanComparable auto* end);
性能 / 兼容性影响:无运行时开销,所有检查在编译期完成;但 GCC 10+ / Clang 12+ / MSVC 19.28+ 才稳定支持,老版本会直接编译失败。
容易踩的坑:LessThanComparable auto 看似方便,但它会抑制 SFINAE,导致重载解析行为和传统模板不同;如果你依赖重载优先级,优先用 template<lessthancomparable t></lessthancomparable> 形式。
组合多个 concept 和 fallback 逻辑
用 && 或 || 组合,但注意短路不生效(全是编译期静态判断):
template<typename t>
concept InputIterator = requires(T t) {
{ *t } -> std::same_as<typename std::iterator_traits>::value_type&&>;
{ ++t } -> std::same_as<t>;
} && std::is_copy_constructible_v<t>;</t></t></typename></typename>
使用场景:你想写一个泛型算法,对随机访问迭代器用 O(1) 下标,对普通输入迭代器只能用 O(n) 遍历——这时得靠 if constexpr + std::is_same_v 或更干净的 requires 分支:
template<typename it>
void advance_n(It& it, int n) {
if constexpr (std::random_access_iterator<it>) {
it += n;
} else {
while (n-- > 0) ++it;
}
}</it></typename>
关键点:std::random_access_iterator 是标准库提供的 concept,别自己重复造轮子;自己写的 concept 尽量复用已有 trait 和 concept,否则容易和标准行为不一致。
复杂点在于:concept 可以嵌套、偏特化、甚至用于 constexpr if 外部判断,但一旦开始写带条件逻辑的 constraint,就得反复验证错误信息是否依然清晰——很多团队发现,过度分层的 concept 反而让新人更难定位问题。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!









