A
A
Armen2018-01-27 12:36:39
C++ / C#
Armen, 2018-01-27 12:36:39

How to expand parameter pack to pass types to a template function?

Good afternoon! I am writing 2 methods, it took this:
The first method takes a bunch of template parameters, these parameters are expanded into the second method, but no arguments are passed to the function itself.

template <typename... args>
std::shared_ptr<Wt::Dbo::Session> getDboSessionT() {
    DbConnector& dbConnector = DbConnector::instance(dbConfig);
    sessionT = dbConnector.createSession();
    mapClasses<args...>();

    return sessionT;
}

template <typename U, typename... args>
void mapClasses(){
    sessionT->mapClass<U>(U::tableName.c_str());
    std::cout << typeid(U).name() << std::endl;
    std::cout << "MAP TABLE ==================== " << U::tableName << std::endl;
    mapClasses<args...>();
}

But the bottom line is that all the time I get an error about the impossibility of deriving types, since args ... is not unpacked
How to properly unpack parameters and is it possible to do so? doesn't work either
<typeid(args)...>

Answer the question

In order to leave comments, you need to log in

1 answer(s)
E
Evgeny Shatunov, 2018-01-27
@futuarmo

The error seen in the code is a parameter pack usage error.
In the code, you can see the unwinding of the list of parameters, during which the list will inevitably become empty and an attempt will be made to instantiate the mapClasses<>() call. And it is this attempt that leads to the error.
And this error can be removed. To do this, we now have as many as three ways.
The first way is C++17 constexpr if.

template< typename U, typename... args >
void mapClasses()
{
  // ...
  if constexpr( sizeof...( args ) > 0 ) // Все понятно и без слов.
  {
    mapClasses<args...>();
  }
}

The second way is private specialization of the class/structure.
template< typename... args >
struct Map;

template< typename U >
struct Map<U>
{
  static inline void mapClasses()
  {
    // ...
  }
};

template< typename U, typename... args >
struct Map<U, args...>
{
  static inline void mapClasses()
  {
    Map<U>::mapClasses();
    Map<args...>::mapClasses();
  }
};

The third method - the most insidious - is the use of SFINAE in its classical sense.
template< typename U >
void mapClasses()
{
  // ...
}

// SFINAE тут (аргумент функции) выключит вывод шаблона при пустом списке полей.
// В этом случае доступным остается только верхний экземпляр функции.
template< typename U, typename... args >
void mapClasses( char (*)[ sizeof...( args ) > 0 ] = 0 )
{
  mapClasses<U>();
  mapClasses<args...>();
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question