C++20 concepts疑问:对成员类型使用constructible_from约束不生效
问题根因
你写在requires表达式内部的std::constructible_from<typename T::TypeLikeThreeIntegers, int, int, int>;属于简单要求,这类要求只会校验表达式本身的语法合法性,不会校验表达式的求值结果是否为真。std::constructible_from是标准库定义的变量模板,只要你给出的模板参数都是合法类型,这个表达式的语法就是有效的——哪怕std::constructible_from的求值结果是false,也不会触发requires约束失败,这就是你的约束没有生效的核心原因。
另外你之前根据编译器提示添加typename关键字的修改是正确的:T::TypeLikeThreeIntegers是依赖模板参数T的待决类型,C++语法要求这类场景必须显式加typename告知编译器这是一个类型,否则会被解析为静态成员变量,触发编译错误。
修复方案
有两种常见的写法可以实现你的需求:
写法1:使用嵌套要求
在requires块内给需要校验布尔值的表达式加上requires前缀,将其转为嵌套要求,嵌套要求会强制校验后续常量表达式的求值结果为true:
template <typename T> concept Foo = requires { typename T::TypeLikeThreeIntegers; requires std::constructible_from<typename T::TypeLikeThreeIntegers, int, int, int>; };
写法2:拆分约束逻辑
把「存在成员类型」和「成员类型可构造」两个约束用逻辑与直接拼接,写法更简洁:
template <typename T> concept Foo = requires { typename T::TypeLikeThreeIntegers; } && std::constructible_from<typename T::TypeLikeThreeIntegers, int, int, int>;
修改完成后,static_assert(Foo<ShouldNotSatisfyFoo>);就会按照预期触发编译失败,符合你的需求。
内容的提问来源于stack exchange,提问作者nebuch
相关产品推荐
相关产品推荐

