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

C++17中如何展开类型与整数值的多个模板参数包?

C++17中通过模板参数实现类型-整数映射并自动生成operator=是否可行?

需求背景

此前已实现将类型映射到整数值并赋值给type_的硬编码方案,现需改为通过模板参数传入类型集合与对应整数值,自动生成operator=的特化逻辑,替代硬编码。尝试让MyStructure继承带类型和整数参数包的基类时,触发编译错误:

'Types': 如果类模板包含模板参数包,其必须位于模板参数列表的末尾

原问题伪代码

struct MyStructure {
  std::array<std::pair<TYPE, int>> map {
    { int, 1 },
    { char, 2 },
    { double, 4 },
    { std::string, 8 }
  };

  template <typename T>
  auto operator=(const T &arg) {
    // 根据arg的类型,将对应整数值写入成员变量type_
  }
  int type_ = 0;
};

int main() {
  MyStructure myStruct;
  myStruct = 1;             // 应将1存入type_
  myStruct = "Hello world"; // 应将8存入type_
}

尝试的基类实现(触发错误)

template<typename... Types, int...ints> 
class Base_Type  {
// 尝试展开参数包生成特化
};

template<typename... Types, int...ints>
struct MyStructure : Base_Type<Types..., ints...> {
  template <typename T>
  auto operator=(const T &arg) {
    // 检查T是否在Types中
    // 查询Base_Type的T特化获取对应整数值并写入type_
  }
  int type_ = 0;
};

解答:需求完全可行,修正方案如下

C++模板规则确实不允许类模板同时存在两个独立的参数包(如typename... Types和int...ints),因为编译器无法区分两个包的边界。但我们可以通过将类型与对应整数配对,用单个参数包传递所有映射关系的方式解决问题。

实现步骤

  1. 定义单个类型-整数映射的辅助基类
#include <type_traits>
#include <tuple>
#include <utility>
#include <string>

// 封装单个类型与整数的映射关系
template<typename T, int Val>
struct TypeToIntMapping {
    static constexpr int value = Val;
    using type = T;
};
  1. 实现聚合映射的基类
    继承所有传入的TypeToIntMapping实例,提供类型查找与数值获取的逻辑:
// 聚合所有映射关系的基类
template<typename... Mappings>
struct TypeMapBase : Mappings... {
    // 查找对应类型的映射数值
    template<typename T>
    static constexpr int get_value() {
        return get_value_impl<T>(std::index_sequence_for<Mappings...>{});
    }

private:
    // 利用索引序列遍历所有映射,匹配类型并返回对应数值
    template<typename T, size_t... Idx>
    static constexpr int get_value_impl(std::index_sequence<Idx...>) {
        return (... + (std::is_same_v<T, typename std::tuple_element_t<Idx, std::tuple<Mappings...>>::type> 
                       ? std::tuple_element_t<Idx, std::tuple<Mappings...>>::value 
                       : 0));
    }
};
  1. 实现MyStructure类
    继承TypeMapBase,并实现operator=:
template<typename... Mappings>
struct MyStructure : TypeMapBase<Mappings...> {
    template<typename T>
    auto operator=(const T& arg) {
        // 编译期检查类型是否在映射列表中
        static_assert((std::is_same_v<T, typename Mappings::type> || ...), "类型不在映射列表中");
        type_ = this->template get_value<T>();
    }

    int type_ = 0;
};

使用示例

// 定义别名简化映射写法
template<typename T, int Val>
using MapPair = TypeToIntMapping<T, Val>;

int main() {
    // 传入类型-整数的映射集合
    using MyStruct = MyStructure<
        MapPair<int, 1>,
        MapPair<char, 2>,
        MapPair<double, 4>,
        MapPair<std::string, 8>
    >;

    MyStruct myStruct;
    myStruct = 1;                          // type_ = 1
    myStruct = std::string("Hello world"); // type_ = 8
    // myStruct = true; // 触发编译错误:类型不在映射列表中
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 23:24:37