@futuarmo
погромист

Как раскрыть parameter pack для передачи типов в шаблонную функцию?

Добрый день! Пишу 2 метода, потребовалось вот что:
Первый метод принимает пачку шаблонных параметров, эти параметры раскрываются во второй метод, но в саму функцию аргументы не передаются.
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...>();
}

Но суть в том, что всё время получаю ошибку о невозможности выведения типов, так как args... не распаковывается
Как правильно распаковать параметры и можно ли так делать?
<typeid(args)...> тоже не работает
  • Вопрос задан
  • 276 просмотров
Решения вопроса 1
@MarkusD Куратор тега C++
все время мелю чепуху :)
Ошибка, которую видно в коде, это ошибка использования parameter pack.
В коде у тебя видно раскрутку списка параметров, в ходе которой список неизбежно станет пустым и произойдет попытка инстанцировать вызов mapClasses<>(). И именно эта попытка приводит к ошибке.

И эту ошибку можно убрать. Для этого у нас сейчас есть аж целых три способа.

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


Способ второй - частная специализация класа/структуры.
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();
	}
};


Способ третий - самый коварррный - использование SFINAE в классическом его смысле.
template< typename U >
void mapClasses()
{
	// ...
}

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

Войдите, чтобы написать ответ

Похожие вопросы