如何强制C++ concept的类型要求匹配指定类型
C++ Concept 强制类型匹配的实现方法
有两种常用的约束方案,可以分别实现「类型完全匹配」和「类型可转换为指定类型」的需求:
1. 要求类型完全匹配指定类型
用标准库提供的std::same_as概念即可实现,会严格校验两个类型完全一致,比如要求分配器的size_type必须是std::size_t的写法如下:
#include <concepts> #include <cstddef> template<typename Alloc> concept AllocWithExactSizeT = requires { // 首先要求Alloc存在size_type成员类型 typename Alloc::size_type; // 要求size_type和std::size_t完全相同 requires std::same_as<typename Alloc::size_type, std::size_t>; };
2. 要求类型可隐式转换为指定类型
如果不需要完全一致,只要能安全转换为目标类型即可,替换为std::convertible_to约束即可:
template<typename Alloc> concept AllocWithConvertibleSizeT = requires { typename Alloc::size_type; // 要求size_type可以隐式转换为std::size_t requires std::convertible_to<typename Alloc::size_type, std::size_t>; };
补充说明
- 如果需要校验显式转换能力,可以把约束替换为
std::constructible_from<std::size_t, typename Alloc::size_type>,只要目标类型可以用size_type的值显式构造就算符合要求。 - 上述写法已经自带了对成员类型存在性的校验:如果传入的类型没有定义
size_type成员,concept会直接返回不满足,不需要额外编写判断逻辑。 - 如果要额外加更细的约束,比如要求
size_type必须是无符号整型,可以叠加std::unsigned_integral概念:requires std::unsigned_integral<typename Alloc::size_type>;
下面是测试用例参考:
// 完全符合要求的分配器 struct ValidAlloc1 { using size_type = std::size_t; }; static_assert(AllocWithExactSizeT<ValidAlloc1>); static_assert(AllocWithConvertibleSizeT<ValidAlloc1>); // 仅符合可转换要求的分配器 struct ValidAlloc2 { using size_type = unsigned int; // 绝大多数平台下unsigned int可隐式转换为std::size_t }; static_assert(!AllocWithExactSizeT<ValidAlloc2>); static_assert(AllocWithConvertibleSizeT<ValidAlloc2>); // 不符合要求的分配器 struct InvalidAlloc { using size_type = int; // 有符号类型,若要过滤这类可以叠加无符号约束 }; static_assert(!AllocWithExactSizeT<InvalidAlloc>);
内容的提问来源于stack exchange,提问作者Bonita Montero
相关产品推荐
相关产品推荐

