C++:如何通过模板模板参数偏特化简化嵌套模板类检测
问题:检测嵌套模板类型中是否存在特定类A的简洁特质类实现
需求是编写特质类test_for_A,用于判断特定类A是否出现在任意嵌套的模板类型中(例如B<C<A<int>>>属于存在A的情况)。当前实现需要为所有非A的模板类编写重复的部分特化,希望找到更简洁的实现方式,可使用任意C++标准。
现有代码示例:
#include<cassert> template<class T> class A; template<class T> class B; template<class T> class C; template<class T> class D; // 基础特质类模板 template<class T> struct test_for_A; // 匹配A<T>的特化 template<class T> struct test_for_A< A<T> > { constexpr static bool value = true; }; // 匹配B<T>的特化(需要为每个非A类重复编写) template<class T> struct test_for_A< B<T> > { constexpr static bool value = test_for_A<T>::value; }; // 尝试用模板模板参数简化,但写法错误(T不是模板) template<class T, class T1> struct test_for_A< T<T1> > { constexpr static bool value = test_for_A<T1>::value; }; int main() { assert( test_for_A< B<A<B<int>>>::value ); }
尝试用模板模板参数的部分特化替代重复代码,但写法无效,询问是否有更优实现方式。
解决方案
方法1:适配单参数模板类的简洁实现
要匹配任意单参数模板类(除A外),需正确使用模板模板参数声明特化,结合标准库的std::true_type/std::false_type简化代码:
#include<cassert> #include<type_traits> template<class T> class A; template<class T> class B; template<class T> class C; template<class T> class D; // 基础模板:默认情况(非模板类型/未匹配类型)返回false template<class T> struct test_for_A : std::false_type {}; // 匹配A<T>的特化:直接返回true template<class T> struct test_for_A< A<T> > : std::true_type {}; // 匹配任意单参数模板类,递归检查内部类型 template<template<class> class T, class U> struct test_for_A< T<U> > : test_for_A<U> {}; int main() { static_assert(test_for_A< B<A<B<int>>>::value, "A exists"); static_assert(!test_for_A< B<C<D<int>>>::value, "A does not exist"); }
核心逻辑:将特化的第一个参数声明为template<class> class T(模板模板参数),即可匹配所有单参数模板类,递归检查其内部类型参数是否包含A。
方法2:适配任意参数数量的模板类(C++11及以上)
如果需要支持多参数模板类(比如template<class T, class U> class E;),可以用可变模板参数的模板模板参数结合std::disjunction(C17引入,C11可自行实现类似逻辑):
#include<cassert> #include<type_traits> template<class T> class A; template<class T> class B; template<class T, class U> class E; template<class T> struct test_for_A : std::false_type {}; template<class T> struct test_for_A< A<T> > : std::true_type {}; // 匹配任意参数数量的模板类,检查所有模板参数是否包含A template<template<class...> class T, class... Args> struct test_for_A< T<Args...> > : std::disjunction<test_for_A<Args>...> {}; int main() { static_assert(test_for_A< B<A<int>> >::value); static_assert(test_for_A< E<int, A<double>> >::value); // 多参数模板中包含A static_assert(!test_for_A< E<int, double> >::value); }
逻辑说明:std::disjunction会遍历所有模板参数,只要其中任意一个参数包含A,就返回true,完美适配任意嵌套深度和参数数量的模板类。
内容的提问来源于stack exchange,提问作者ritter
相关产品推荐
相关产品推荐

