I\'d like to use partial template specialization in order to \'break down\' an array (which is created at compile time) into a parameter pack composed of its values (to inte
See OP's own answer or, for possibly instructive but more verbose (and less useful) approach, revision 2 of this answer.
(This answer originally contained an approach using a minor C++20 feature (that a lambda without any captures may be default constructed), but inspired by the original answer the OP provided a much neater C++20 approach making use of the fact that a constexpr
std::array
falls under the kind of literal class that may be passed as a non-type template parameter in C++20 (given restraints on its ::value_type
), combined with using partial specialization over the index sequence used to unpack the array into a parameter pack. This original answer, however, made use of a technique of wrapping std::array
into a constexpr
lambda (>=C++17) which acted as a constexpr
(specific) std::array
creator instead of an actual constexpr
std::array
. For details regarding this approach, see revision 2 of this answer)
Following OP's neat approach, below follows an adaption of it for C++17, using a non-type lvalue reference template parameter to provide, at compile time, a reference to the array to the array to struct target.
#include
#include
#include
#include
#include
// Parameter pack structure (concrete target for generator below).
template
struct ConsumerStruct
{
// Use tuple equality testing for testing correctness.
constexpr auto operator()() const { return std::tuple{s...}; }
};
// Generator: FROM std::array TO Consumer.
template typename Consumer,
typename Indices = std::make_index_sequence >
struct Generator;
template typename Consumer,
std::size_t... I>
struct Generator >
{
using type =
Consumer::type>::type::value_type,
arr[I]...>;
};
// Helper.
template typename Consumer>
using Generator_t = typename Generator::type;
// Example usage.
int main()
{
// As we want to use the address of the constexpr std::array at compile
// time, it needs to have static storage duration.
static constexpr std::array arr{{1, 5, 42}};
constexpr Generator_t cs;
static_assert(cs() == std::tuple{1, 5, 42});
return 0;
}
Note that this approach places a restriction on the std::array
instance in that it needs to have static storage duration. If one wants to avoid this, using a constexpr
lambda which generates the array may be used as an alternative.