如何简洁规范地检查C++结构体成员是否符合指定concept
问题原因
requires 表达式的复合要求中,{ expr } -> 概念名的检查规则是验证概念名<decltype((expr))>是否成立。对于作为左值的结构体非静态成员变量,decltype((expr))会推导为左值引用类型,导致std::floating_point<float&>返回false,这就是原有校验失败的根本原因。
通用解决方案
直接在概念后追加auto占位符即可:auto的类型推导规则会自动丢弃顶层引用和cv限定符,直接匹配成员的原始类型,完全不需要额外写decltype、类型转换或者自定义辅助概念。
修改后的可运行代码如下:
#include <concepts> struct foo { float f; }; static_assert(std::floating_point<decltype(foo::f)>); template<typename T> concept has_fp_member = requires (T t) { // 仅需在原有concept后追加auto即可 { T::f } -> std::floating_point auto; }; static_assert(has_fp_member<foo>);
方案优势
- 完全符合C++标准惯用写法,可读性极强
- 通用适配所有标准库或自定义concept,不需要修改concept本身
- 校验多个成员时代码非常简洁,不会出现大量
decltype嵌套:template<typename T> concept valid_struct = requires (T t) { { T::a } -> std::integral auto; { T::b } -> std::ranges::input_range auto; { T::c } -> std::derived_from<Base> auto; { T::d } -> std::convertible_to<std::string_view> auto; }; - 支持灵活调整约束规则:如果需要保留cv限定符或引用约束,直接调整占位符写法即可,比如要检查成员为const浮点类型写
-> std::floating_point<const auto>,要检查为浮点左值引用写-> std::same_as<float&>。
内容的提问来源于stack exchange,提问作者Jean-Michaël Celerier
相关产品推荐
相关产品推荐

