如何将多模板参数类适配到单模板参数Wrapper类?
问题:适配多模板参数类到单模板参数的Wrapper中
我需要将带有两个模板参数的Special类,适配到仅接受单模板参数类作为模板参数的Wrapper类中。尝试通过SpecialBridge做适配层,但编译报错,编译器无法识别SpecialBridge<T>::BT的类型。
原代码
// test.cpp // Base class class Base { public: int data_base = 1; }; // A derive class template<typename P> class Derived : public Base { P data_child; }; // A wrapper to accept any type similar to Derived<P> as the base class template<template<typename> class BT, typename P> class Wrapper : public BT<P> { int do_something; }; // However, a special derived class need an extra template parameter template<typename T, typename P> class Special : public Derived<P> { T special; }; // Try to fit Special into the type of BT of Wrapper template<typename T> class SpecialBridge { public: template<typename P> using BT = Special<T, P>; }; // actually define the type to use (Error!) template<typename T, typename P> using Actual = Wrapper<SpecialBridge<T>::BT, P>; int main() { Actual<int, int> obj; return obj.data_base; }
编译错误信息
$ g++ -std=c++17 test.cpp -o test test.cpp:40:47: error: type/value mismatch at argument 1 in template parameter list for ‘template<template<class> class BT, class P> class Wrapper’ 40 | using Actual = Wrapper<SpecialBridge<T>::BT, P>; | ^ test.cpp:40:47: note: expected a class template, got ‘SpecialBridge<T>::BT’ test.cpp: In function ‘int main()’: test.cpp:44:3: error: ‘Actual’ was not declared in this scope 44 | Actual<int, int> obj; | ^~~~~~ test.cpp:44:10: error: expected primary-expression before ‘int’ 44 | Actual<int, int> obj; | ^~~ test.cpp:45:10: error: ‘obj’ was not declared in this scope 45 | return obj.data_base; | ^~~
解决方案
错误原因
SpecialBridge<T>::BT是依赖于模板参数T的模板别名,编译器在模板语境下无法自动推断它是一个模板,需要显式用template关键字声明,否则会被当成普通类型处理,导致类型不匹配。
修正代码
只需要修改Actual的定义,在BT前添加template关键字:
template<typename T, typename P> using Actual = Wrapper<SpecialBridge<T>::template BT, P>;
完整修正后的代码
// test.cpp // Base class class Base { public: int data_base = 1; }; // A derive class template<typename P> class Derived : public Base { P data_child; }; // A wrapper to accept any type similar to Derived<P> as the base class template<template<typename> class BT, typename P> class Wrapper : public BT<P> { int do_something; }; // However, a special derived class need an extra template parameter template<typename T, typename P> class Special : public Derived<P> { T special; }; // Try to fit Special into the type of BT of Wrapper template<typename T> class SpecialBridge { public: template<typename P> using BT = Special<T, P>; }; // Fixed definition template<typename T, typename P> using Actual = Wrapper<SpecialBridge<T>::template BT, P>; int main() { Actual<int, int> obj; return obj.data_base; }
其他可选方案(C++20)
如果使用C++20,也可以用模板lambda简化适配,不需要额外定义SpecialBridge:
template<typename T, typename P> using Actual = Wrapper<[]<typename U>(U) -> Special<T, U> {}, P>;
不过这种方式需要编译器支持C++20的模板lambda特性。
内容的提问来源于stack exchange,提问作者Wei Song
相关产品推荐
相关产品推荐

