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});
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.