Как развернуть шаблон пакета параметров "разархивированным" способом?

Скажем, у меня есть вариативная функция, foo:

template <typename... Args>
void foo(Args... args)
{
    // some work
}

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

Скажи, если я позвоню

bar(x, y, z);

Это будет иметь тот же эффект, что и

foo(x.begin(), x.end(), y.begin(), y.end(), z.begin(), z.end());

Как реализовать такие bar()?

template <typename... Args>
void bar(Args... args)
{
    // what should I put here?
    // foo( (args.begin(), args.end()) ... );  // doesn't work 
}

1 ответ

Если вы можете использовать C++17, примените std::apply:

template<class ...  Conts>
void bar(Conts&& ... c) {
    auto t = std::make_tuple( std::make_tuple(c.begin(),c.end())... );
    // tuple< tuple<C1.begin,C1.end>, tuple<C2.begin,C2.end>, ... >    [1]
    std::apply( [](auto&&... tuples){
            auto oneTuple = std::tuple_cat(std::forward<decltype(tuples)>(tuples)...);
            // tuple< C1.begin(), C1.end(), C2.begin(), C2.end(), ...>   [2]
            std::apply([](auto&&... its){
                foo(std::forward<decltype(its)>(its)...); /// all iterators begin/end    [3]
            }, oneTuple);
        }, t);
}
  1. Создать кортеж из tuple<begin,end> для всех записей
  2. Использовать apply чтобы получить все кортежи, созданные на первом шаге, и сделать из них один путем объединения - используйте tuple_cat
  3. Использовать снова apply чтобы извлечь все итераторы из кортежа, созданного на втором шаге, передайте их все в foo

Демо

Другие вопросы по тегам