Расширенный пакет параметров вариационного шаблона для вызовов функций

Я ищу что-то вроде этого:

template< typename T>  
void func(T t)
{
}

template< typename... Parms> 
void anyFunc( Parms... p)
{
    func<Parms>(p)... ;  //error 
    func(p)... ;         //error 
}

Если расширение пакета параметров выполняется внутри другого вызова функции, он работает:

template< typename T>
int some(T t)
{}

template< typename... Parms>
void func(Parms ...p)
{}

template< typename... Parms>
void somemore(Parms... p)
{
   func( some(p)...);
}

int main() 
{
 somemore(1,2,3,4,10,8,7, "Hallo");
}

Расширение пакета параметров также будет работать для списка инициализаторов базового класса.

Есть ли какое-либо решение, которое также будет работать для функций, которые возвратят 'void'. Вышеописанное обходное решение не будет, в то время как использование вызовов функций, возвращающих void внутри списка параметров, никогда не будет работать.

Любые идеи?

Ответы

Ответ 1

К сожалению, как вы заметили, расширение пакета параметров действует только в определенных контекстах, где парсер ожидает список записей, разделенный запятыми, - контексты, в которых запятая является просто синтаксическим разделителем, а не оператором запятой. Это, возможно, недостаток в текущем тексте.

Уродливое обходное решение:

func((some(p), 0)...);

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

Ответ 2

Как насчет небольшого вспомогательного класса:

template <typename Func, typename A, typename ...Args> struct Caller
{
  static void call(Func & f, A && a, Args && ...args)
  {
    f(std::forward<A>(a));
    Caller<Func, Args...>::call(f, args...);
  }
};

template <typename Func, typename A> struct Caller<Func, A>
{
  static void call(Func & f, A && a)
  {
    f(std::forward<A>(a));
  }
};

template <typename Func, typename ...Args>
void Call(Func & f, Args && ...args)
{
  Caller<Func, Args...>::call(f, std::forward<Args>(args)...);
}

Затем вы можете поместить в код клиента следующее:

void foo(A);
Call(foo, a1, a2, a3);