为什么类型约束std::convertible_to可仅使用一个模板参数?
原因解释
这是C++20针对概念(Concept)用作类型约束时专门定义的语法规则,属于标准明确支持的合法用法,和概念偏特化、模板重载没有任何关系,核心逻辑是「隐式填充缺失的第一个模板参数」。
核心规则
对于任意需要N个模板参数的概念,当你把它用在以下两种场景作为类型约束时:
- 修饰
auto占位符(比如你的用例:std::convertible_to<A> auto x) - 修饰模板形参声明(比如你的用例:
template<std::convertible_to<A> T>)
如果你传入的实参数量是N-1个,编译器会自动把当前被约束的类型作为概念的第一个模板参数,和你传入的参数拼接成完整的实参列表完成约束检查。
对应你用的std::convertible_to,它的标准定义是双参数概念:
template<typename From, typename To> concept convertible_to = /* 隐式转换+显式转换的约束实现 */
你写的std::convertible_to<A> auto x中:
- 被约束的类型是
x的推导类型,记为T - 你只传了1个实参
A,比要求的2个少1个 - 编译器自动补全约束为
std::convertible_to<T, A>,刚好就是你观察到的「要求T可转换为A」的效果。
等价写法验证
你提到的两种写法确实完全等价:
| 简化写法 | 完整展开写法 |
|---|---|
cpp void foo(std::convertible_to<A> auto x) {} | cpp template<typename T> requires std::convertible_to<T, A> void foo(T x) {} |
cpp template<typename T, std::convertible_to<T> S> void foo(S x) {} | cpp template<typename T, typename S> requires std::convertible_to<S, T> void foo(S x) {} |
通用适配性
这个规则对所有多参数概念都生效,这也是你测试std::derived_from也有同样效果的原因:std::derived_from<Base> auto x会自动补全为std::derived_from<T, Base>,约束T是Base的派生类。
内容的提问来源于stack exchange,提问作者aradarbel10
相关产品推荐
相关产品推荐

