Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Unpack variadic template to initializer_list and call two functions at once

I have two vectors:

std::vector<int> v1{ 1, 2, 3 };
std::vector<int> v2{ 4, 5, 6 };

I want to create an object of std::initializer_list which holds iterators to the first and last elements of above vectors.

I want to have a function with a variadic template:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

template<class... Ts>
void foo(Ts... args)

and inside above function I want to unpack all arguments. So far I implemented:

template<class... Ts>
void foo(Ts... args)
{
  std::initializer_list<std::vector<int>::iterator> il{
    (std::begin(args), std::end(args))...
  };
}

int main()
{
  std::vector<int> v1{ 1, 2, 3 };
  std::vector<int> v2{ 4, 5, 6 };

  foo(v1, v2);
}

but it doesn’t work as expected due to operator,. Current implementation creates initializer_list with two iterators. What I want in this case is to have an initializer_list with 4 iterators pointing to the first and one past the end element of these two vectors. I want it to be begin, end, begin, end.

>Solution :

You can make a new pack which is double the length:

#include <vector>
#include <utility>
#include <tuple>

namespace detail {

template<std::size_t... I, class... Ts>
void foo_impl(std::index_sequence<I...>, Ts&... args) {
    std::initializer_list<std::vector<int>::iterator> il{
        [&]() -> std::vector<int>::iterator {
            auto& vec = std::get<I/2u>(std::tie(args...));
            return I % 2u == 0u ? std::begin(vec) : std::end(vec);
        }()...
    };

    // ...
}

}

template<class... Ts>
void foo(Ts... args) {
    return detail::foo_impl(std::make_index_sequence<sizeof...(args)*2u>{}, args...);
}

Or consider if you need an initializer_list at all. You might be able to use an array:

template<class... Ts>
void foo(Ts... args) {
    std::vector<int>::iterator il[sizeof...(args)*2u];
    {
        auto* p = std::begin(il);
        (((*p++ = std::begin(args)), (*p++ = std::end(args))), ...);
    }

    // ...
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading