固定参数模板模板类型与对应成员模板别名比较失败原因求解
问题原因
这个问题是C++标准对模板等价性的判定规则导致的:
两个模板被判定为等价的前提是它们的模板参数列表完全匹配,且模板定义的表达式等价:
- 对于可变参数模板
variadic_args,它本身的声明是template<typename...> struct variadic_args,模板参数列表是可变参数包;而designated<variadic_args>::tt_type的声明是template<typename... T> using tt_type = TT<T...>,两者模板参数列表都是可变参数包,且别名的定义直接转发参数包给原模板,符合模板等价规则,所以你的is_same_tt的偏特化能匹配成功,返回true。 - 对于固定参数模板
fixed_args_number,它本身的声明是template<typename AT, typename BT, typename CT> struct fixed_args_number,模板参数是固定3个类型参数;而designated<fixed_args_number>::tt_type的模板参数还是可变参数包,两者模板参数列表本身就不匹配,不符合等价要求,因此不会被判定为同一个模板,偏特化匹配失败,返回false。
额外说明:你写的is_same_tt的形参是template<typename...> class,C++17及以上版本允许固定参数数量的模板绑定到这种接受可变参数的模板模板形参上,这只是绑定兼容性,不代表两个模板本身等价。
适配需求的解决方案
你的需求是判断两个模板模板参数是否“功能等价”(即给定相同的输入参数能得到相同的实例化结果),可以抛弃直接依赖原生模板等价匹配的逻辑,改用测试用例实例化对比的方案:
#include <type_traits> namespace eld::util::traits { namespace detail { // 测试用类型组,可根据你实际使用的模板参数数量扩展 template<size_t ArgCount, typename... Ts> struct test_type_group; // 覆盖你常用的参数数量对应的测试类型 using test_groups = std::tuple< test_type_group<3, int, void, char*>, // 对应3参数模板的测试用例 test_type_group<2, int, float>, // 有2参数模板可以保留该测试项 test_type_group<1, void*> // 有1参数模板可以保留该测试项 >; template<template<typename...> class ATT, template<typename...> class BTT, typename Group> struct test_group_match; template<template<typename...> class ATT, template<typename...> class BTT, size_t N, typename... Ts> struct test_group_match<ATT, BTT, test_type_group<N, Ts...>> : std::is_same<ATT<Ts...>, BTT<Ts...>> {}; template<template<typename...> class ATT, template<typename...> class BTT, typename... Groups> struct test_all_groups : std::conjunction<test_group_match<ATT, BTT, Groups>...> {}; template<template<typename...> class ATT, template<typename...> class BTT, typename... Groups> struct test_all_groups<ATT, BTT, std::tuple<Groups...>> : test_all_groups<ATT, BTT, Groups...> {}; } template<template<typename...> class ATT, template<typename...> class BTT> struct is_same_tt : detail::test_all_groups<ATT, BTT, detail::test_groups> {}; template<template<typename...> class ATT, template<typename...> class BTT> inline constexpr bool is_same_tt_v = is_same_tt<ATT, BTT>::value; }
这个实现会用你定义的所有测试类型组分别实例化两个模板,所有组的实例化结果都相同时才会返回true,可以覆盖固定参数、可变参数模板和别名模板的等价判断场景,只要测试用例覆盖了你实际使用的参数数量即可。
内容的提问来源于stack exchange,提问作者Sergey Kolesnik
相关产品推荐
相关产品推荐

