Группировка аргументов пакета параметров в initializer_list - PullRequest
0 голосов
/ 21 марта 2020

Я пытаюсь выяснить, как взять плоский пакет параметров и преобразовать его в initializer_list, где аргументы пакета логически сгруппированы. Допустим, у меня есть что-то вроде:

void doSomething(std::initializer_list<std::pair<const char *, int>> args) {
    ...
}

Я хочу написать вариант c variadi, который принимает пары в виде плоского списка аргументов. Что-то вроде:

template <typename ... Args>
void doSomethingFlattened(const char *name, int value, Args... args) {
    doSomething({/*what goes here?*/});
}

doSomethingFlattened("a", 1, "b", 2, "c", 3);
doSomethingFlattened("a", 1, "b", 2, "c"); // compile error

Возможно ли это в C ++ 17?

Ответы [ 2 ]

2 голосов
/ 21 марта 2020

Я бы сделал что-то вроде этого:

void doSomething(std::initializer_list<std::pair<const char *, int>> list)
{
    for (auto [a,b] : list)
        std::cout << a << ':' << b << '\n';
}

template <std::size_t ...I, typename ...Args>
void doSomethingFlattened_low(std::index_sequence<I...>, const Args &... args)
{
    auto t = std::tie(args...);
    doSomething({{std::get<I*2>(t), std::get<I*2+1>(t)}...});
}

template <typename ...Args>
void doSomethingFlattened(const Args &... args)
{
    static_assert(sizeof...(Args) % 2 == 0, "Expected even number of arguments.");
    doSomethingFlattened_low(std::make_index_sequence<sizeof...(Args) / 2>{}, args...);
}

(запустить на g cc .godbolt.org)

1 голос
/ 21 марта 2020

Вы можете сделать

template <std::size_t ... Is, typename Tuple>
void doSomethingFlattenedImpl(std::index_sequence<Is...>, const Tuple& t) {
    doSomething({std::make_pair(std::get<2 * Is>(t), std::get<2 * Is + 1>(t))...});
}

template <typename ... Args>
void doSomethingFlattened(Args... args) {
    static_assert(sizeof...(Args) % 2 == 0);
    doSomethingFlattenedImpl(std::make_index_sequence<sizeof...(Args) / 2>{},
                             std::make_tuple(args...));
}

Демо

...