能否实现integral_pack_traits提取整数序列包装类的值类型?
关于
integral_pack_traits模板类实现的可行性分析 我尝试实现一个模板类来提取整数序列(比如
std::index_sequence)的元素类型,代码大致如下:template <typename> struct integral_pack_traits; template <template <template <typename T, T...> class> class Wrapper, template <typename T, T...> class P> struct integral_pack_traits<Wrapper<P>> { using type = T; };期望例如
std::index_sequence对应的type为std::size_t,请问该实现是否可行?注:原代码片段存在template <typename Pack> struct integral_pack_traits; template <template <t...这类不完整内容。
咱们先直接说结论:这个实现不可行,核心问题是你的模板参数匹配逻辑和std::index_sequence的实际签名完全不匹配,我来一步步拆解原因,再给你靠谱的实现方案。
问题出在哪?
std::index_sequence的实际签名:它是一个接受非类型模板参数的模板,标准签名是template<std::size_t...> class index_sequence——也就是说,它的参数是std::size_t类型的数值,不是类型参数。而你代码里的P是template <typename T, T...> class,这个签名要求P是一个先接受类型参数T、再接受T类型非参数的模板,和std::index_sequence完全对不上。Wrapper<P>的匹配逻辑:你的模板试图匹配“被Wrapper包裹的模板P”,但std::index_sequence<...>本身是一个实例化后的具体类型,根本没有被任何Wrapper包裹,所以你的特化模板永远不会被触发。
正确的实现方案
根据你兼容的C++版本,有两种靠谱的实现方式:
方案一:C++17及以上(通用型)
利用C++17引入的auto非类型模板参数,可以一次性匹配所有整数序列模板:
#include <utility> #include <cstddef> #include <type_traits> template <typename> struct integral_pack_traits; // 匹配所有形如 Template<Value...> 的类型,其中Template接受auto...非类型参数 template <template <auto...> class Template, auto... Values> struct integral_pack_traits<Template<Values...>> { // 提取序列中第一个值的类型;如果序列为空,可加静态断言提示 using type = decltype(Values); }; // 测试验证 static_assert(std::is_same_v<typename integral_pack_traits<std::index_sequence<0, 1, 2>>::type, std::size_t>); // 也支持自定义的整数序列模板 template <int... N> struct int_sequence {}; static_assert(std::is_same_v<typename integral_pack_traits<int_sequence<1, 3, 5>>::type, int>);
方案二:兼容C++11/14(针对标准序列)
如果需要兼容更早的C++标准,因为auto非类型参数还不支持,我们可以直接针对标准库的序列模板做特化:
#include <utility> #include <cstddef> #include <type_traits> template <typename> struct integral_pack_traits; // 针对std::index_sequence的特化 template <std::size_t... Indices> struct integral_pack_traits<std::index_sequence<Indices...>> { using type = std::size_t; }; // 针对更通用的std::integer_sequence的特化(支持任意整数类型) template <typename T, T... Values> struct integral_pack_traits<std::integer_sequence<T, Values...>> { using type = T; }; // 测试验证 static_assert(std::is_same_v<typename integral_pack_traits<std::index_sequence<0, 1>>::type, std::size_t>); static_assert(std::is_same_v<typename integral_pack_traits<std::integer_sequence<int, 1, 2, 3>>::type, int>);
总结
你最初的实现方向偏了——我们需要匹配的是接受非类型整数参数的模板实例,而不是“被Wrapper包裹的模板”。上面的两种方案都能准确提取出整数序列的元素类型,满足你的需求。
内容的提问来源于stack exchange,提问作者prestokeys
相关产品推荐
相关产品推荐

