如何让BB模板类支持带任意附加模板参数的A1派生类?
你的思路方向是对的,但当前代码存在几个语法和模板参数匹配的问题,咱们一步步修正并实现你想要的功能:
问题分析
你想要让BB的模板参数NN支持任意数量模板参数且继承自A1<K>的类,但你的初步实现里:
- 模板参数顺序不合理,导致可变参数包无法正确匹配;
enable_if中的NN<K, typename...>写法错误,无法正确展开参数;- 不必要的特化写法不符合模板匹配规则;
- 友元声明没有适配新的
BB模板参数结构。
正确实现方案
下面是可以在VS2017/GCC中正常编译运行的代码,我会逐部分解释:
#include <type_traits> #include <iostream> // 前置声明A1 template <typename K> class A1; // BB主模板:使用可变参数模板模板参数NN,支持任意参数的NN template <typename K, template <typename...> class NN = A1, // NN是任意参数的模板 typename... Types, // NN的额外模板参数包 // 检查NN<K, Types...>是否继承自A1<K> typename = std::enable_if_t<std::is_base_of_v<A1<K>, NN<K, Types...>>>> class BB; // A1的定义:调整友元声明适配BB的新模板结构 template <typename K> class A1 { public: // 允许BB<K, A1>(即默认NN的情况)访问私有成员 friend class BB<K, A1>; }; // 双参数的A2,继承A1<K> template <typename K, typename V> class A2 : public A1<K> { V local; }; // 三参数的A3,继承A1<K>(测试多参数场景) template <typename K, typename V, typename U> class A3 : public A1<K> { V v; U u; }; // BB的实现:不需要特化,直接用主模板实现即可 template <typename K, template <typename...> class NN, typename... Types, typename> class BB { NN<K, Types...>* ref; public: BB() : ref{new NN<K, Types...>{}} { std::cout << "BB constructed with " << typeid(NN<K, Types...>).name() << "\n"; } // 加上析构函数避免内存泄漏 ~BB() { delete ref; } }; int main() { BB<size_t> b1{}; // 默认使用A1<size_t> BB<size_t, A2, char> b2{}; // 使用A2<size_t, char> BB<size_t, A3, int, double> b3{}; // 使用A3<size_t, int, double> }
关键细节说明
- 可变模板模板参数:
template <typename...> class NN允许NN是任意数量模板参数的类模板(比如A1是单参数,A2是双参数,A3是三参数)。 - 参数包传递:
typename... Types用于接收NN的额外模板参数,在BB内部通过NN<K, Types...>实例化出具体的类。 - 类型检查:
std::enable_if_t<std::is_base_of_v<A1<K>, NN<K, Types...>>>确保实例化后的NN子类一定继承自A1<K>,不符合条件的会在编译期报错。 - 友元适配:
A1中的friend class BB<K, A1>确保默认情况下BB可以访问A1的私有成员(如果后续需要扩展,也可以改为更通用的友元声明)。
编译运行说明
- 如果你使用C++11(VS2017支持),需要把
std::enable_if_t改为typename std::enable_if<...>::type,把std::is_base_of_v改为std::is_base_of<...>::value,即:typename = typename std::enable_if<std::is_base_of<A1<K>, NN<K, Types...>>::value>::type
内容的提问来源于stack exchange,提问作者Frank Buddha
相关产品推荐
相关产品推荐

