You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何使用std::is_arithmetic_v的C++20 concept(requirement expression)无法强制执行类型约束?

为何使用std::is_arithmetic_v的C++20 concept(requirement expression)无法强制执行类型约束?

我最近跟着Marius Bancila在2022年出版的《Template Metaprogramming with C++: Learn everything about C++ templates and unlock the power of template metaprogramming》这本书里的例子实现C++20概念时,踩了个坑——我写了两个看似等价的arithmetic概念定义,结果其中一个根本起不到约束类型的作用。

先给大家看看这两个版本:

版本1(无效的约束)

template<typename T>
concept arithmetic = requires(T a, T b) {
    { std::is_arithmetic_v<T> } -> std::convertible_to<bool>;
};

版本2(有效的约束)

template<typename T>
concept arithmetic = std::is_arithmetic_v<T>;

最开始我以为这俩是一回事,但实际测试发现,版本1居然允许std::string这种明显不是算术类型的参数通过约束,这完全不符合预期!

后来我才搞明白问题出在哪:

  • 版本2是直接把std::is_arithmetic_v<T>这个常量表达式作为概念的核心条件,只有当它的值为true时,类型T才满足这个概念,这是正确的用法。
  • 版本1的问题在于,我用了requires表达式里的简单要求(就是带大括号的那种),它只会检查std::is_arithmetic_v<T>这个表达式本身是否合法,以及它的结果能不能转换成bool——但不管这个结果是true还是false!哪怕T是std::string,std::is_arithmetic_v<std::string>是false,但这个表达式本身是合法的(它就是个bool常量),所以整个requires表达式都会被判定为满足,概念自然就失效了。

如果非要在requires表达式里实现这种类型检查,得用嵌套要求,也就是再加一层requires关键字来包裹常量表达式,像这样:

template<typename T>
concept arithmetic = requires(T a, T b) {
    requires std::is_arithmetic_v<T>;
};

这种写法就会强制要求std::is_arithmetic_v<T>必须为true,才能满足概念,和版本2的效果是一致的。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 13:43:07