Variadic Dispatch Function - PullRequest
       26

Variadic Dispatch Function

2 голосов
/ 05 ноября 2019

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

#include <iostream>
#include <vector>

enum param_type{typeA,typeB};

template <param_type PT> struct Container{
  int value;
  Container(int v):value(v){}
};

int f(Container<typeA> param){
  std::cout<<"Got typeA with value "<<param.value<<std::endl;
  return param.value;
}
int f(Container<typeB> param){
  std::cout<<"Got typeB with value "<<param.value<<std::endl;
  return param.value;
}

Мое текущее решение использует рекурсивный шаблон переменной для делегирования работы.

void g(){}
template <typename T,typename...R>
void g(T param,R...rest){
  f(param);
  g(rest...);
}

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

template <typename...T> // TODO: Use concepts once they exist.
void h(T... params){
  // f(params);...
  // f(params)...;    // Fail to compile.
  // {f(params)...};
  std::vector<int> v={f(params)...}; // Works
}

Пример использования

int main(){
  auto a=Container<typeA>(5);
  auto b=Container<typeB>(10);
  g(a,b);
  h(a,b);
  return 0;
}

Существует ли элегантный синтаксис для этого расширения в C ++?

1 Ответ

4 голосов
/ 05 ноября 2019

В C ++ 17: используйте выражение сгиба с оператором запятой.

template <typename... Args>
void g(Args... args)
{
    ((void)f(args), ...);
}

До C ++ 17: запятая с 0, а затем разверните в списке фигурных инициализаторов int массив. Дополнительный 0 предназначен для того, чтобы гарантировать, что массив нулевого размера не создан.

template <typename... Args>
void g(Args... args)
{
    int arr[] {0, ((void)f(args), 0)...};
    (void)arr;                            // suppress unused variable warning
}

В обоих случаях выражение вызова функции приводится к void, чтобы избежать случайного вызова пользовательского определенияoperator,.

...