Есть ли какой-нибудь элегантный способ? (введите пакет параметров) - PullRequest
0 голосов
/ 12 марта 2019

Я хочу создать функцию, которая будет принимать типы и снова вызывать себя с помощью цикла или рекурсии.

То, что я уже пробовал, было ниже, но оно вызывало только базовую функцию (Вызывается базовая функция с AModuleкласс и не вызывать функцию с BModule.

class AModule {
};
class BModule {
};

auto main() -> int {
  init<AModule, BModule>()
  return 0;
}

template<typename Module>
void init() {
  // BASE FUNCTION
  // Do something
}

template<typename... Modules>
void init() {
  (init<Modules>(), ...)
}

Ответы [ 2 ]

3 голосов
/ 12 марта 2019

В коде вашего примера вы используете сворачивание шаблонов, новую функцию C ++ 17, которая позволяет вам избежать рекурсии.

Но, чтобы избежать конфликта имен, я предлагаю вызватьбазовая версия по-другому;скажем do_something()

template<typename Module>
void do_something() {
  // BASE FUNCTION
  // Do something
}

template<typename... Modules>
void init() {
  (do_something<Modules>(), ...);
}

Если вы действительно хотите использовать рекурсивный способ, вы можете сделать что-то следующим образом

template <int = 0>
void init ()
 {
  // stop recursion; do nothing
 }

template <typename Head, typename ... Tail>
void init () 
 {
   // do something with Head

   // recursively call init()
   init<Tail...>();
 }

Хитрость заключается в том, что вызов init<Tail...>();, пока Tail... нет'empty' называется рекурсивной версией Head / Tail....

Когда Tail... пусто, init<Tail...>() равно init<>(), поэтому версия Head / Tail... не соответствуетбольше (нет Head), но соответствует версии int = 0;так что init<>() становится init<0>(), и случай бездействия останавливает рекурсию.

1 голос
/ 12 марта 2019

В вашем коде (после исправления синтаксических ошибок) оба вызова init() были действительны для одного параметра шаблона, поэтому вызов был неоднозначным.Если для вызова multi-init требуется как минимум 2 параметра, эта неоднозначность устраняется.

// bogus type that just prints an error message including the type it is parameterized with
template<typename T>
struct printer;

template<typename Module>
void init() {
 printer<Module>{}; // this is an error just to show you that it's getting called with both types
}

// only call this if it's called with 2 or more types, otherwise just use the other init()
template<typename T1, typename T2, typename... Modules>
void init() {
    init<T1>();
    init<T2>();
  (init<Modules>(), ...);
}

class AModule {
};
class BModule {
};

auto main() -> int {
  init<AModule, BModule>();
  return 0;
}

в прямом эфире: https://godbolt.org/z/D-eh2G

...