Пакет параметров одного шаблона для нескольких функций - PullRequest
0 голосов
/ 11 декабря 2019

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

template<typename ...Pack>
void func1(Pack... params);

template<typename ...Pack>
void func2(Pack... params);

template<typename ...Pack>
void func3(Pack... params);

template<typename ...Pack>
void func4(Pack... params);

Есть ли какой-нибудь способ избежать этого избыточного повторения? Например, что-то вроде:

template<typename ...Pack>
{
    void func1(Pack... params);
    void func2(Pack... params);
    void func3(Pack... params);
    void func4(Pack... params);
}

Ответы [ 3 ]

2 голосов
/ 11 декабря 2019

Pre C ++ 20 ответ: Нет, вы ничего не можете сделать, чтобы получить такой синтаксис. Лучшее, что вы можете сделать, - это создать макрос, который сделает за вас большую работу.

C ++ 20. Вы можете использовать auto для типа параметра функции, который является синтаксическим сахаром для написания шаблона, такого какэто для лямбды в настоящее время. Это дало бы вам

void func1(auto... params);
void func2(auto... params);
void func3(auto... params);
void func4(auto... params);
1 голос
/ 11 декабря 2019

Если вы можете использовать C ++ 17 ... может быть, вы можете определить одну функцию с дополнительным параметром шаблона, который является номером функции, и использовать if constexpr для разделения тел отдельных функций.

Я имею в виду что-то следующее

template <int Id, typename ... Pack>
void func (Pack ... params)
 {
   if constexpr ( 1 == id )
    { /* body of func1() */ }
   else if constexpr ( 2 == id )
    { /* body of func2() */ }
   else if constexpr ( 3 == id )
    { /* body of func3() */ }
   // else // etc...
 }

Для вызова func() вам нужно явно указать целочисленный параметр шаблона

func<1>("abc"); // equivalent to func1("abc");

Как заметил Натан Оливер, когда имена функцийявляются важными и описательными (а не простыми перечислениями), использование целочисленного параметра шаблона дает вам полное описание.

В этом случае вместо int вы можете добавить значение перечисления дополнительнопараметр шаблона. С описательными именами для значений enum.

Что-то вроде

enum funcId
 {
   a_complex_and_descriptive_func_id,
   another_complex_func_id,
   a_third_complex_func_id // , etc...
 }     

template <funcId Id, typename ... Pack>
void func (Pack ... params)
 {
   if constexpr ( a_complex_and_descriptive_func_id == id )
    { /* body of first function */ }
   else if constexpr ( another_complex_func_id == id )
    { /* body of second function */ }
   else if constexpr ( a_third_complex_func_id == id )
    { /* body of third function */ }
   // else // etc...
 }

и вызов становится

func<a_complex_and_descriptive_func_id>("abc");
1 голос
/ 11 декабря 2019

Попробуйте обернуть их внутри структуры. Если вы хотите, чтобы они были независимы от какого-либо состояния объекта, вы должны объявить их статическими.

template <typename ...Pack>
struct FunctionHolder
{
    static void func1(Pack... params);

    static void func2(Pack... params);
};

LIVE SAMPLE

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...