Suppose I have a compile-time constexpr array and a variadic class template with a set of non-type parameters of the same type as the elements of the array.
My objective is to instantiate the class template with the values from the array:
struct Container
{
int containee[3];
};
constexpr Container makeContainer();
template <int... Elements> class Foo;
Foo<makeContainer().containee[0],
makeContainer().containee[1],
makeContainer().containee[2]> foo;
The above code works well. However, I'm quite unhappy about having to manually index the array whenever I need to instantiate the Foo
template. I would like the compiler to do that for me automatically:
Foo<Magic(makeContainer().containee)> foo;
I did some RTFM at cppreference, but that didn't help. I'm aware of std::forward<>()
, but it cannot be applied to template argument lists.
Change makeContainer
to a struct
with a constexpr operator()
or a constexpr
lambda (C++17). A function pointer will not work here.
struct makeContainer
{
constexpr auto operator()() const
{
return Container{/* ... */};
}
};
Use std::make_index_sequence
and std::index_sequence
to generate a compile-time sequence of the indices:
template <typename C>
constexpr auto fooFromContainer(const C& container)
{
return fooFromContainerImpl(container, std::make_index_sequence<3>{});
}
Create a new constexpr
container instance through C
, then expand the sequence to index the elements in a constant expression:
template <typename C, std::size_t... Is>
constexpr auto fooFromContainerImpl(const C& container, std::index_sequence<Is...>)
{
constexpr auto c = container();
return Foo<c.containee[Is]...>{};
}
complete example on wandbox.org
Just for fun, here's a C++20 implementation:
struct container { int _data[3]; };
template <int... Is>
struct foo
{
constexpr auto t() const { return std::tuple{Is...}; }
};
template <typename C>
constexpr auto foo_from_container(const C& c)
{
return []<std::size_t... Is>(const auto& c, std::index_sequence<Is...>)
{
return foo<c()._data[Is]...>{};
}(c, std::make_index_sequence<3>{});
}
int main()
{
constexpr auto r = foo_from_container([]{ return container{42, 43, 44}; });
static_assert(r.t() == std::tuple{42, 43, 44});
}
live example on wandbox.org
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With