代码之家  ›  专栏  ›  技术社区  ›  Wei Song

使用减少的模板参数数量推导模板类

  •  2
  • Wei Song  · 技术社区  · 11 月前

    我有一个 wrapper 需要a的课程 template<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 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;
          |          ^~~
    

    我有什么办法可以把这件事做好吗。很抱歉,我描述这个问题的方式不太标准。示例代码或多或少是可以自我解释的。

    1 回复  |  直到 11 月前
        1
  •  2
  •   JeJo    11 月前

    从错误消息中:

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

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

    因此, the template keyword is necessary 因为 BT 是一个依赖名称(它取决于模板参数 T ).

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

    现在,您的代码将按预期工作: See live demo

        2
  •  1
  •   user12002570    11 月前

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

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

    Working demo