2013-03-04 6 views
8

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

template<typename R, typename Args...> 
R myFunction(Data &data, void *function) { 
    auto f = (R (*)(Args...))function; 
    return f(read<Args1>(data, 1), read<Args2>(data, 2), ...);// <-- This is the problem 
} 

Данный код, конечно, не подлежит компиляции. Есть ли способ исправить это? Есть ли способ сделать это без вариационных шаблонов без чрезмерного дублирования кода?

+2

Я уверен, что вы можете избежать указателя объекта на функцию-указатель. – sellibitze

+0

@sellibitze: Это проблема? Потому что я могу иметь только пользовательские данные указателя void *, которые передаются из функции C. –

+0

Данные могут быть 'void *'. Это функция, которая является «void *», что вызывает беспокойство. –

ответ

14

Да, это возможно:

// we need a compile-time helper to generate indices 
template< std::size_t... Ns > 
struct indices 
{ 
    typedef indices< Ns..., sizeof...(Ns) > next; 
}; 

template< std::size_t N > 
struct make_indices 
{ 
    typedef typename make_indices< N - 1 >::type::next type; 
}; 

template<> 
struct make_indices<0> 
{ 
    typedef indices<> type; 
}; 

С этими помощниками требуется один форвардер для вашей функции, как это:

template<typename R, typename... Args, std::size_t... Ns> 
R myFunctionImpl(void *Data, void *function, indices<Ns...>) { 
    auto f = (R (*)(Args...))function; 
    return f(read<Args>(Data, Ns + 1)...);// +1 because indices is zero-based 
} 

template<typename R, typename... Args> 
R myFunction(void *Data, void *function) { 
    return myFunctionImpl< R, Args... >(Data, function, typename make_indices<sizeof...(Args)>::type()); 
} 

EDIT: Как это работает? Сначала мы определяем размер argument packArgs - sizeof.... make_indices<N>::type затем расширяется до indices<0,1,2,...,N-1>. Он задается в качестве дополнительного параметра для функции реализации (от форвардера, который только создает фиктивный экземпляр), поэтому аргумент дедукции запускается на стороне функции реализации и помещает сгенерированные индексы в пакет аргументов Ns.

Функция реализации теперь имеет два пакета аргументов с одинаковым размером, а именно Args и Ns. При расширении через эллипсис ... эллипсис расширяет полное выражение , которое оно применяется и оно параллельно расширяет все пакеты параметров! В приведенном выше примере это выражение равно read<Args>(Data, Ns+1), которое прекрасно расширяется в псевдокоде OPs.

+0

можете ли вы опубликовать простой пример? –

+2

Я просто сделал. Что отсутствует в примере, который я дал? –

+0

Отсутствует реальный пример. С 'main()' и некоторыми функциями (с 1,2,3 параметрами). Как вы используете эти функции и структуры? –

Смежные вопросы