2014-01-25 2 views
0

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

//ValueArray contains a vector of a variant type. 

// Pulls out an argument from a ValueArray. 
template<typename Arg> 
inline Arg 
_processParam(ValueArray& args) { 
    Arg arg = static_cast<Arg&>(args[ 0 ]); 
    args.erase(0, true); 
    return arg; 
} 


/// Do the Function call. Args is a variadic template pack. 
call(fnPtr, _processParam<Args>(args)...); 

/// The call expands to: 
(*fnPtr)(params...); 

Однако проблема в том, что _processParam (арг) ... расширение вытаскивая арг по типу в обратном порядке. Например, ValueArray из [1, 1.4] будет вытащен как двойной, затем и int. Есть ли способ вывести аргументы правильно и переносимым образом?

+0

Оценка аргумента выражения вызова функции (разделенные ',' s, которые не являются запятыми) * неупорядочены *. Для некоторых компиляторов, таких как g ++, порядок является справа налево, т. Е. Сначала вычисляется выражение самого правого аргумента. Кажется, ваша программа имеет Undefined Behavior. – dyp

+0

Большинство компиляторов оценивают как справа, так и слева направо? Если это так, я могу сейчас просто справиться с этими делами. Иначе есть ли способ привязать индекс к вызову функции? – h4tch

ответ

1

Избавьтесь от erase и добавьте свой индекс. Не мутируйте данные, используемые при других вычислениях параметров при выполнении вызова функции, поскольку порядок не определен (что позволяет компилятору переупорядочить их для повышения эффективности или фазы miin).

Вам нужно будет добавить еще один уровень косвенности, чтобы сделать это легко:

template<unsigned...>struct indexes {}; 

template<unsigned num, unsigned... Is>struct make_indexes: 
    make_indexes<num-1, num-1, Is...>{}; 
template<unsigned...Is>struct make_indexes<0,Is...>:indexes<Is...>{}; 

template<typename... Args, unsigned...Is> 
void do_call(indexes<Is...>, ValArray& arr){ 
    call(fnPtr, ProcessParam<Args>(arr[Is])...); 
} 

где ProcessParam теперь занимает элемент не массив, и использовать его как:

do_call<Args...>(make_indexes<sizeof...(Args)>(), arr); 
+0

не телефонный ответ: может быть typso – Yakk

+0

Спасибо, я не мог понять, как получить индексы. Это похоже на операцию типа zip. – h4tch

+0

@ DanH. ответ улучшился. Вы создаете пакет индексов того же размера, а затем расширяете их в parrallel. Обратите внимание, что C++ 1y будет иметь 'index_sequence', который выполняет большую часть вышеуказанного шаблона. – Yakk

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