我有一个以 为参数的wrappertemplate<typename> class。但是,我有一个带有额外参数的类,例如template<typename T, typename P> Special,我想将其放入包装器类的参数中。

我能想到的唯一解决方案如下:

// 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;
}

然而,c++17 和 c++20 都声称相同。编译器无法推断SpecialBridge<T>::BT

$ g++ -std=c++17 test.cpp -o test
test.cpp:40:47: error: type/value mismatch at argument 1 in template parameter list fortemplate<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 ‘int44 |   Actual<int, int> obj;
      |          ^~~
test.cpp:45:10: error: ‘obj’ was not declared in this scope
   45 |   return obj.data_base;
      |          ^~~

有什么方法可以正确地做到这一点?抱歉,我描述这个问题的方式不太标准。示例代码或多或少是可以自我解释的。

8

  • 为什么不直接将包装器的第一个参数改为template<template<typename...> class BT


    – 


  • 将第一个参数更改为 后的template<typename...>。或者甚至是这个


    – 


  • WrapperP为 BT<P>提供参数。Special使用时,我希望有类似的东西Wrapper<Special<T>, P>,其中T直接带有SpecialP在实际使用时提供。这可以用吗typename...?请详细说明。


    – 

  • 您可以将包装器更改为template<template<typename...> class BT, typename... P>class Wrapper : public BT<P...> {};。然后您可以编写Wrapper<Special, int, int> w;


    – 


  • 1
    我明白了。这似乎有效。我需要回到实际项目,看看它是否能解决问题。你想给出一个简单的答案吗?一旦证明有效,我一定会接受它。非常感谢!


    – 


最佳答案
2

从错误信息来看:

note:   expected a class template, got 'SpecialBridge<T>::BT'

很明显,编译器无法理解SpecialBridge<T>::BT您定义的别名中的模板。

因此,因为BT是一个依赖名称(它依赖于模板参数T)。

template<typename T, typename P>
using Actual = Wrapper<SpecialBridge<T>::template BT, P>;
//                                      ^^^^^^^^^  ---> add this!

现在,你的代码将按预期工作:

0

您可以使用参数包,如下所示:

template<template<typename...> class BT, typename... P> requires(sizeof...(P)<=2)
class Wrapper: public BT<P...>  
{
  int do_something;
};
int main() {

    Wrapper<Special, int, int> w;
    return w.data_base;
}

0