Extension of constexpr array in nonpig type template parameter set

Suppose I have a constexpr array for compilation and a variational class template with a set of off-peak parameters of the same type as the array elements.

My goal is to create an instance of a class template with values ​​from an 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 am very unhappy with the need to manually index the array whenever I need to instantiate an Foo template. I would like the compiler to do this automatically for me:

 Foo<Magic(makeContainer().containee)> foo; 

I did some RTFM in cppreference, but that didn't help. I know std::forward<>() , but it cannot be applied to template argument lists.

+8
c ++ templates template-meta-programming constexpr variadic-templates
source share
1 answer
  • Change makeContainer to struct with constexpr operator() or constexpr lambda (C ++ 17). The function pointer does not work here.

     struct makeContainer { constexpr auto operator()() const { return Container{/* ... */}; } }; 
  • Use std::make_index_sequence and std::index_sequence to generate a sequence of compilation indices:

     template <typename C> constexpr auto fooFromContainer(const C& container) { return fooFromContainerImpl(container, std::make_index_sequence<3>{}); } 
  • Create a new instance of the constexpr container via 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]...>{}; } 

full example on wandbox.org


Just for fun, here is 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(rt() == std::tuple{42, 43, 44}); } 

live example on wandbox.org

+7
source share

All Articles