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

如何为模板类内的枚举类实现通用format_as,避免重复包装?

解决模板类内部枚举的format_as通用模板编译问题

你写的模板版format_as之所以编译失败,核心原因是typename S<T>::Side属于C++的非推导上下文。编译器没办法从传入的S<int>::Side这类枚举值,反向推导出模板参数T,导致libfmt在尝试匹配格式化函数时找不到合适的实例,最终触发编译错误。

下面提供两种可行的解决方案:

方案1:将format_as作为模板类的友元函数定义在类内部

这是最简洁的解决方式,利用ADL(依赖于参数的查找)让libfmt自动定位到对应枚举的格式化函数,完全避开模板推导问题:

#include <fmt/format.h>

template<typename T>
struct S {
    enum class Side { Left, Right };

    // 每个T实例都会生成对应的format_as非模板函数
    friend auto format_as(Side side) {
        switch(side) {
            case Side::Left: return "L";
            case Side::Right: return "R";
        }
        __builtin_unreachable();
    }
};

int main() {
    S<int>::Side s1 = S<int>::Side::Left;
    S<double>::Side s2 = S<double>::Side::Right;
    fmt::print("{} {}\n", s1, s2); // 输出 "L R"
    return 0;
}

方案2:用类型特征关联枚举与模板参数T

如果不想把格式化逻辑放在类内部,可以定义类型特征模板,提前绑定枚举类型和对应的T,再实现通用format_as模板:

#include <fmt/format.h>
#include <type_traits>

template<typename T>
struct S {
    enum class Side { Left, Right };
};

// 类型特征:从S<T>::Side提取对应的T
template<typename E>
struct side_to_T;

template<typename T>
struct side_to_T<typename S<T>::Side> {
    using type = T;
};

template<typename E>
using side_to_T_t = typename side_to_T<E>::type;

// 通用format_as模板,推导枚举类型后提取T
template<typename SideEnum>
auto format_as(SideEnum side) {
    using T = side_to_T_t<SideEnum>;
    switch(side) {
        case S<T>::Side::Left: return "L";
        case S<T>::Side::Right: return "R";
    }
    __builtin_unreachable();
}

int main() {
    S<int>::Side s1 = S<int>::Side::Left;
    S<double>::Side s2 = S<double>::Side::Right;
    fmt::print("{} {}\n", s1, s2);
    return 0;
}

方案说明

  • 方案1中,每个S<T>实例都会生成一个专属的format_as(S<T>::Side)非模板函数,libfmt通过ADL机制可以直接匹配到该函数,无需模板推导。
  • 方案2通过类型特征提前建立枚举类型与T的映射,format_as的模板参数是可被推导的枚举类型,再通过特征提取出对应的T,解决了原模板无法推导T的问题。

内容的提问来源于stack exchange,提问作者NoSenseEtAl

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 18:07:47