如何用C++ Concepts实现强类型Trait,无需继承且简化代码?
方案实现(基于C++20,无需继承)
核心思路是用位掩码枚举标记支持的运算权限,结合C++20支持的lambda作为非类型模板参数实现唯一类型标记,完全不需要单独定义Tag结构体,一行即可完成强类型声明。
第一步:定义运算权限枚举
#include <cstdint> #include <concepts> // 运算权限位掩码 enum class StrongOp : uint32_t { None = 0, Addable = 1 << 0, Subtractable = 1 << 1, Incrementable = 1 << 2, Comparable = 1 << 3, Multipliable = 1 << 4, Divisible = 1 << 5, // 按需扩展更多运算类型 }; // 重载位运算符方便权限组合 constexpr StrongOp operator|(StrongOp a, StrongOp b) { return static_cast<StrongOp>(static_cast<uint32_t>(a) | static_cast<uint32_t>(b)); } constexpr StrongOp operator&(StrongOp a, StrongOp b) { return static_cast<StrongOp>(static_cast<uint32_t>(a) & static_cast<uint32_t>(b)); }
第二步:定义强类型基类与权限校验concept
// 强类型定义:底层类型、支持的运算权限、唯一标记(默认用匿名lambda自动生成) template<typename Underlying, StrongOp Ops, auto UniqueTag = []{}> struct StrongT { Underlying val; static constexpr StrongOp enabled_ops = Ops; }; // 基础concept:判断是否为自定义强类型 template<typename T> concept StrongType = requires { T::enabled_ops; }; // 按需定义各运算对应的concept template<typename T> concept Addable = StrongType<T> && (T::enabled_ops & StrongOp::Addable) != StrongOp::None; template<typename T> concept Incrementable = StrongType<T> && (T::enabled_ops & StrongOp::Incrementable) != StrongOp::None; template<typename T> concept Comparable = StrongType<T> && (T::enabled_ops & StrongOp::Comparable) != StrongOp::None;
第三步:实现通用运算符重载
template<Addable T> T operator+(const T& a, const T& b) { return T{a.val + b.val}; } template<Incrementable T> T& operator++(T& t) { t.val++; return t; } template<Incrementable T> T operator++(T& t, int) { auto tmp = t; t.val++; return tmp; } template<Comparable T> auto operator<=>(const T& a, const T& b) { return a.val <=> b.val; } // 按需扩展其余运算符的通用实现
第四步:一行声明自定义强类型
完全不需要单独定义Tag结构体,支持内联声明:
// 支持加法、自增的纳秒类型 using Nanos = StrongT<size_t, StrongOp::Addable | StrongOp::Incrementable>; // 支持加法、比较的索引类型 using Index = StrongT<size_t, StrongOp::Addable | StrongOp::Comparable>; // 支持加法、除法的股价类型(即使权限和其他类型一致,加匿名lambda也会生成独立类型,避免混用) using StockPrice = StrongT<double, StrongOp::Addable | StrongOp::Divisible, []{}>;
方案优势
- 完全无继承,符合要求
- 代码冗余度极低,新增强类型仅需一行声明,无需额外编写Tag结构体
- 运算权限组合直观,用位或即可灵活拼接需要支持的运算符
- 所有运算符逻辑集中管理,维护成本低
- 强类型隔离性强,即使底层类型、权限完全一致,只要添加不同的唯一标记就不会发生隐式混用
C++17兼容版本
如果需要兼容C++17,仅需将唯一标记改为类型参数,声明时仅需要前置声明Tag即可,依然比原有方案简洁:
// C++17版本强类型定义 template<typename Underlying, StrongOp Ops, typename UniqueTag> struct StrongT { Underlying val; static constexpr StrongOp enabled_ops = Ops; }; // 声明强类型仅需要前置声明Tag,不需要写结构体内部的trait定义 struct NanosTag; using Nanos = StrongT<size_t, StrongOp::Addable | StrongOp::Incrementable, NanosTag>;
内容的提问来源于stack exchange,提问作者NoSenseEtAl
相关产品推荐
相关产品推荐

