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

如何在C++17中泛化std::conditional_t适配多枚举类型?

问题描述

我有一个根据给定参数计算特定对象的函数(比如从图中提取重要节点)。计算过程中可能会分配内存,有时候我只需要返回计算结果,有时候希望同时返回结果和计算所用的内存。

针对这种二元场景,我之前是这么实现的:

enum class what {
    what1,  // 返回值类型:int
    what2   // 返回值类型:std::pair<int, std::vector<int>>
};

template <what w>
std::conditional_t<w == what::what1, int, std::pair<int, std::vector<int>>>
calculate_something(const param& p) { ... }

现在我想把这个方案扩展到更多选项的枚举类型:

enum class list_whats {
    what1,
    what2,
    what3,
    what4,
    what5
};

一种可行的方式是嵌套多个std::conditional_t:

template <list_whats what>
std::conditional_t<
    what == list_whats::what1,
    int,
    std::conditional_t<
        what == list_whats::what2,
        float,
        ....
    >
>
calculate_something(const param& p) { ... }

但这种写法太繁琐,不够优雅。有没有更简洁的C++17实现方式?

补充说明
需要实现return_something函数,使得下面的main函数可以正常编译运行:

int main() {
    int s1 = return_something<list_whats::what1>();
    s1 = 3;

    float s2 = return_something<list_whats::what2>();
    s2 = 4.0f;

    double s3 = return_something<list_whats::what3>();
    s3 = 9.0;

    std::string s4 = return_something<list_whats::what4>();
    s4 = "qwer";

    std::vector<int> s5 = return_something<list_whats::what5>();
    s5[3] = 25;
}

解决方案

方案一:模板特化(直观易维护)

针对每个枚举值单独特化函数,每个分支可以实现独立的计算逻辑:

#include <string>
#include <vector>

enum class list_whats {
    what1,
    what2,
    what3,
    what4,
    what5
};

// 主模板声明
template <list_whats What>
auto return_something();

// 特化每个枚举对应的返回类型和实现
template <>
auto return_something<list_whats::what1>() {
    return int{}; // 替换为实际计算逻辑
}

template <>
auto return_something<list_whats::what2>() {
    return float{};
}

template <>
auto return_something<list_whats::what3>() {
    return double{};
}

template <>
auto return_something<list_whats::what4>() {
    return std::string{};
}

template <>
auto return_something<list_whats::what5>() {
    return std::vector<int>{4}; // 初始化大小为4,适配main中的s5[3]操作
}

// 测试代码
int main() {
    int s1 = return_something<list_whats::what1>();
    s1 = 3;

    float s2 = return_something<list_whats::what2>();
    s2 = 4.0f;

    double s3 = return_something<list_whats::what3>();
    s3 = 9.0;

    std::string s4 = return_something<list_whats::what4>();
    s4 = "qwer";

    std::vector<int> s5 = return_something<list_whats::what5>();
    s5[3] = 25;
}

方案二:编译期类型映射表(集中管理对应关系)

用std::tuple集中管理枚举和返回类型的映射,适合计算逻辑有共性的场景:

#include <string>
#include <vector>
#include <tuple>
#include <type_traits>

enum class list_whats {
    what1,
    what2,
    what3,
    what4,
    what5
};

// 枚举与返回类型的映射表,顺序和枚举值一一对应
using ReturnTypeMap = std::tuple<int, float, double, std::string, std::vector<int>>;

// 辅助工具:将枚举值转换为tuple的索引
template <list_whats What>
constexpr size_t EnumToIndex() {
    return static_cast<size_t>(What);
}

// 主函数模板,根据索引获取对应返回类型
template <list_whats What>
std::tuple_element_t<EnumToIndex<What>(), ReturnTypeMap> return_something() {
    using ReturnType = std::tuple_element_t<EnumToIndex<What>(), ReturnTypeMap>;
    
    // 统一或分支处理计算逻辑
    if constexpr (std::is_same_v<ReturnType, std::vector<int>>) {
        return ReturnType{4}; // 适配main中的s5[3]操作
    } else {
        return ReturnType{};
    }
}

// 测试代码
int main() {
    int s1 = return_something<list_whats::what1>();
    s1 = 3;

    float s2 = return_something<list_whats::what2>();
    s2 = 4.0f;

    double s3 = return_something<list_whats::what3>();
    s3 = 9.0;

    std::string s4 = return_something<list_whats::what4>();
    s4 = "qwer";

    std::vector<int> s5 = return_something<list_whats::what5>();
    s5[3] = 25;
}

方案对比

  • 模板特化:每个枚举值的实现完全独立,适合不同返回类型需要差异化计算逻辑的场景,代码直观,易调试维护。
  • 编译期映射表:枚举与类型的对应关系集中管理,新增枚举值只需修改映射表和初始化逻辑,适合返回类型与枚举一一对应且计算逻辑有共性的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 08:30:51