C++17下实现std::tuple类型映射的问题求助
问题:std::tuple类型间顺序映射的编译错误与修正
需求与逻辑
- 实现两种
std::tuple类型间的转换:类型相同则建立映射,重复类型按输入序列的先后顺序匹配输出序列的对应项,最终需确保所有输出类型都被成功映射。 - 核心匹配逻辑:
while 存在未处理的<input, output>对
如果当前输入类型 == 当前输出类型
记录映射关系,同时推进输入、输出序列到下一项
否则
仅推进输入序列到下一项
断言:所有输出类型均已完成映射
当前实现与错误
现有代码
template <auto> struct value {}; template <auto... Vals> struct value_sequence {}; template <class... Vals> struct placeholder {}; template <auto... As, auto... Bs> constexpr value_sequence<As..., Bs...> operator+(value_sequence<As...>, value_sequence<Bs...>) { return {}; } template <size_t Idx, size_t... Idxs, size_t OtherIdx, size_t... OtherIdxs, class T, class... Ts, class OtherT, class... OtherTs> constexpr auto mapper(const std::index_sequence<Idx, Idxs...>&, const std::index_sequence<OtherIdx, OtherIdxs...>&, const placeholder<T, Ts...>&, const placeholder<OtherT, OtherTs...>&) { if constexpr (sizeof...(OtherIdxs) == 0) { static_assert(std::is_same_v<T, OtherT>); return value_sequence<Idx>{}; } else if constexpr (std::is_same_v<T, OtherT>) { return value_sequence<Idx>{} + mapper(std::index_sequence<Idxs...>{}, std::index_sequence<OtherIdxs...>{}, placeholder<Ts...>{}, placeholder<OtherTs...>{}); } else { return mapper(std::index_sequence<Idx, Idxs...>{}, std::index_sequence<OtherIdxs...>{}, placeholder<T, Ts...>{}, placeholder<OtherTs...>{}); } }
调用方式
mapper(std::make_index_sequence<sizeof...(Ts)>{}, std::make_index_sequence<sizeof...(OtherTs)>{}, placeholder<Ts...>{}, placeholder<OtherTs...>{})
编译错误
error C2672: 'mapper': no matching overloaded function found,指向else if分支的递归调用。
问题分析与修正
核心问题
- 递归逻辑错误:原代码中类型不匹配时,错误地推进了输出序列而非输入序列,完全违背需求逻辑。
- 缺少空序列重载:原模板仅接受非空的
std::index_sequence作为参数,当输入序列被推进至空时,无匹配的重载函数,导致编译失败。 - 边界处理不完善:未处理输出序列已完成映射(为空)的终止条件,以及输入耗尽但输出未完成的断言场景。
修正后的完整代码
#include <tuple> #include <utility> template <auto> struct value {}; template <auto... Vals> struct value_sequence {}; template <class... Vals> struct placeholder {}; // 合并两个value_sequence template <auto... As, auto... Bs> constexpr value_sequence<As..., Bs...> operator+(value_sequence<As...>, value_sequence<Bs...>) { return {}; } // 终止条件1:输出序列已全部映射完成 template <size_t... Idxs, class... Ts> constexpr auto mapper(const std::index_sequence<Idxs...>&, const std::index_sequence<>&, const placeholder<Ts...>&, const placeholder<>&) { return value_sequence<>{}; } // 终止条件2:输入序列耗尽但输出未完成,触发断言 template <size_t... OtherIdxs, class... OtherTs> constexpr auto mapper(const std::index_sequence<>&, const std::index_sequence<OtherIdxs...>&, const placeholder<>&, const placeholder<OtherTs...>&) { static_assert(sizeof...(OtherIdxs) == 0, "Input sequence exhausted before all output types are mapped"); return value_sequence<>{}; } // 主递归逻辑 template <size_t Idx, size_t... Idxs, size_t OtherIdx, size_t... OtherIdxs, class T, class... Ts, class OtherT, class... OtherTs> constexpr auto mapper(const std::index_sequence<Idx, Idxs...>&, const std::index_sequence<OtherIdx, OtherIdxs...>&, const placeholder<T, Ts...>&, const placeholder<OtherT, OtherTs...>&) { if constexpr (std::is_same_v<T, OtherT>) { // 类型匹配:记录输入索引,同时推进两个序列 return value_sequence<Idx>{} + mapper(std::index_sequence<Idxs...>{}, std::index_sequence<OtherIdxs...>{}, placeholder<Ts...>{}, placeholder<OtherTs...>{}); } else { // 类型不匹配:仅推进输入序列,输出序列保持当前位置 return mapper(std::index_sequence<Idxs...>{}, std::index_sequence<OtherIdx, OtherIdxs...>{}, placeholder<Ts...>{}, placeholder<OtherT, OtherTs...>{}); } }
测试示例
// 输入tuple:int, float, int, double;输出tuple:int, double using InputTuple = std::tuple<int, float, int, double>; using OutputTuple = std::tuple<int, double>; constexpr auto mapping = mapper( std::make_index_sequence<std::tuple_size_v<InputTuple>>{}, std::make_index_sequence<std::tuple_size_v<OutputTuple>>{}, placeholder<std::tuple_element_t<0, InputTuple>, std::tuple_element_t<1, InputTuple>, std::tuple_element_t<2, InputTuple>, std::tuple_element_t<3, InputTuple>>{}, placeholder<std::tuple_element_t<0, OutputTuple>, std::tuple_element_t<1, OutputTuple>>{} ); // mapping 类型为 value_sequence<0, 3>,对应输入的第1个int和第4个double
内容的提问来源于stack exchange,提问作者bpmckinnon
相关产品推荐
相关产品推荐

