Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.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
Цитата Qraizer @
ну если этот dispatcher::add() сделать как-нибудь constexpr...

не только add, но и dispatch. И разбор регэкспов в компил тайм. Ну то есть теоретически это возможно, но практически...

Цитата Axis @
Понадобилось узнать порядковый нормер типа в вариадике при вызове:

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
Цитата alexeibs @
Я недавно делал обертку над C API яваскрипт-движка WebKit.

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

Автор: NeoApostol 13.03.14, 07:13
Посмотри еще здесь может что пригодится
http://habrahabr.ru/post/183830/

Автор: Axis 13.03.14, 10:25
Принцип понял, получилось, завелось, адаптировал для своего решения, ибо тупл мне не подходит.

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)