Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум на Исходниках.RU > C/C++: Общие вопросы > Возможно ли определить порядковый номер аргумента при развертке variadic. |
Автор: Axis 12.03.14, 11:51 |
Понадобилось узнать порядковый нормер типа в вариадике при вызове: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> caller(get<typename std::decay<Args>::type>(what)...); caller - функциональный объект Args - его аргументы (variadic) get - функция получения значения аргумента из what, по совместительству выполняет конвертацию элемента к нужному типу what - по сути массив с аргументами (а вообще контейнер с перегруженными []) Пришли идеи: 1. Сделать список типов из вариадика и искать нужный тип в нём, не подходит, т.к. типы могут повторяться 2. Сделать какую-нить обёртку и при обвявлении caller использовать, не подходит из-за корявости 3. Считать внутри, но порядок вызовов get для аргументов неопределен Варианты иссякли Возможно ли узнать порядковый номер аргумента вариадика, для которого производится вызов get? |
Автор: Qraizer 12.03.14, 13:01 |
Что-то я даже не могу себе представить код, которому не то, что бы это пригодилось, хотя бы синтаксис использования им сего номера не представляется. Можешь набросать что-либо экзампловое? P.S. Навскидку если: собрать из Args некий std::tuple. |
Автор: Axis 12.03.14, 13:07 |
Вообще хочется что-то типа этого реализовать <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> void worker1(const std::string& a, int b) { ... } void worker2(int a) { ... } dispatcher d; d.add("/(\\w+)/(\\d+)", worker1); d.add("/(\\d+)", worker2); d.dispatch("/action/123"); d.dispatch("/14231"); В итоге по регулярке разбираю, через lexical_cast привожу к нужному типу, в итоге возвращается массив захватов, его и хотелось прокинуть с использованием вариадиков, а не кучей классов под нужное кол-во аргументов. Внутрях используется для хранения обработчика type erasure. |
Автор: MyNameIsIgor 12.03.14, 13:14 |
Цитата Axis @ В итоге по регулярке разбираю, через lexical_cast привожу к нужному типу, в итоге возвращается массив захватов, его и хотелось прокинуть с использованием вариадиков Не очень понимаю как вы хотите это осуществить. Дело в том, что variadic - сущность времени компиляции, а парсинг regexp'а и соответствующие им действия - run-time. Короче, не понятно для чего нужен порядковый номер... |
Автор: Qraizer 12.03.14, 15:20 |
Не, ну если этот dispatcher::add() сделать как-нибудь constexpr... Теперь не понятно, как связать эти два поста, Axis. Ладно, подойдём с другой стороны. <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> Что не так с этим кодом? template <typename ...Args> void called(Args ...args) { std::tuple<Args...> t(args...); /* ... */ } |
Автор: jack128 12.03.14, 18:07 |
не только add, но и dispatch. И разбор регэкспов в компил тайм. Ну то есть теоретически это возможно, но практически... http://stackoverflow.com/questions/1501409...plate-expansion |
Автор: alexeibs 12.03.14, 19:49 |
Я недавно делал обертку над C API яваскрипт-движка WebKit. Я реализовал возможность регистрации произвольной std::function в качестве js-функции, которую можно вызывать из js-кода. Для этого нужно было вектор js-значений преобразовать в типизированные аргументы std::function. Где-то на Stack Overflow нашел вот такой код (проверял в VS 2013) <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> // call function with arguments expanded from std::tuples template<typename Result, typename... Args, typename Tuple, std::size_t ... Indices> Result callFunctionWithTupleImpl(std::function<Result (Args...)>& f, Tuple&& t, std::index_sequence<Indices...>) { return f(std::get<Indices>(std::forward<Tuple>(t))...); } template<typename Result, typename... Args, typename Tuple> Result callFunctionWithTuple(std::function<Result (Args...)>& f, Tuple&& t) { using IndexSequence = std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>; return callFunctionWithTupleImpl(f, std::forward<Tuple>(t), IndexSequence()); } Здесь испольуется std::index_sequence, которого пока нет в стандарте, но обещают добавить в С++ 14. Реализацию взял из WebKit. <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> // Implementation of std::index_sequence from WebKit (Source/WTF/wtf/StdLibExtras.h) namespace std { // Compile-time integer sequences // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3658.html // (Note that we only implement index_sequence, and not the more generic integer_sequence). template<size_t... indexes> struct index_sequence { static size_t size() { return sizeof...(indexes); } }; template<size_t currentIndex, size_t...indexes> struct make_index_sequence_helper; template<size_t...indexes> struct make_index_sequence_helper<0, indexes...> { typedef std::index_sequence<indexes...> type; }; template<size_t currentIndex, size_t...indexes> struct make_index_sequence_helper { typedef typename make_index_sequence_helper<currentIndex - 1, currentIndex - 1, indexes...>::type type; }; template<size_t length> struct make_index_sequence : public make_index_sequence_helper<length>::type { }; } // namespace std |
Автор: Axis 13.03.14, 06:47 |
Что-то подобное и нужно, спс. Подобное еще надо для обёртки над шаблонизатором ClearSilver, задача точно такаяже, только для функций самого шаблонизатора вызываемых из шаблонов. Посмотрю, попробую разобраться. |
Автор: NeoApostol 13.03.14, 07:13 |
Посмотри еще здесь может что пригодится http://habrahabr.ru/post/183830/ |
Автор: Axis 13.03.14, 10:25 |
Принцип понял, получилось, завелось, адаптировал для своего решения, ибо тупл мне не подходит. |