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

如何用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, []{}>;

方案优势

  1. 完全无继承,符合要求
  2. 代码冗余度极低,新增强类型仅需一行声明,无需额外编写Tag结构体
  3. 运算权限组合直观,用位或即可灵活拼接需要支持的运算符
  4. 所有运算符逻辑集中管理,维护成本低
  5. 强类型隔离性强,即使底层类型、权限完全一致,只要添加不同的唯一标记就不会发生隐式混用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 04:54:03