Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deduce a template class with reduced number of template parameters

I have a wrapper class which takes a template<typename> class as a parameter. However, I have a class with extra parameters, such as template<typename T, typename P> Special, and I would like to fit it into the parameter of the wrapper class.

The only solution I can figure out is like the following:

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

However, both c++17 and c++20 claim the same. The compiler cannot deduct the type of 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;
      |          ^~~

Is there any way I can do this properly? Sorry for my not-so-standard way of describing this problem. The example code is more or less self-explainable.

like image 380
Wei Song Avatar asked Oct 19 '25 14:10

Wei Song


1 Answers

From the error message:

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

it is clear, that the compiler couldn't understand the SpecialBridge<T>::BT is a template in the alias you defined.

Therefore, the template keyword is necessary because BT is a dependent name (it depends on the template parameter T).

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

Now, your code will work as expected: See live demo

like image 158
JeJo Avatar answered Oct 21 '25 03:10

JeJo