1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
|
#include <iostream>
#include <iomanip>
namespace detail_
{
/////////////////////////////////////// assign_helper ////////////////////////////////
template < typename T, std::size_t N, std::size_t POS = 0 > struct assign_helper
{
template< typename FIRST, typename... REST > // called when size of the pack is at least one
static void assign( T (&vec)[N], FIRST&& first, REST&&... rest )
{
vec[POS] = std::forward<FIRST>(first) ;
assign_helper<T,N,POS+1>::assign( vec, std::forward<REST>(rest)... ) ;
}
static void assign( T (&)[N] ) {} // do nothing: called when the parameter pack is empty
};
template < typename T, std::size_t N > struct assign_helper< T, N, N > // out of range: do nothing
{ template < typename... REST > static void assign( T (&)[N], const REST&... ) {} };
////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////// missing argument privider ////////////////////////////
template < typename T, std::size_t N, bool NO_MISSING_ARGS, typename... U >
struct missing_argument_provider // NO_MISSING_ARGS == true: no missing argument
{
static void assign( T (&vec)[N], U&&... pack )
{ detail_::assign_helper< T, N >::assign( vec, std::forward<U>(pack)... ) ; }
};
template < typename T, std::size_t N, typename... U >
struct missing_argument_provider< T, N, false, U... > // NO_MISSING_ARGS == false: at least one missing argument
{
static void assign( T (&vec)[N], U&&... pack ) // add one more argument, and try again
{ missing_argument_provider< T, N, ( sizeof...(U) >= (N-1) ), U..., T >::assign( vec, std::forward<U>(pack)..., T{} ) ; }
};
////////////////////////////////////////////////////////////////////////////////////////
}
// assign values from the pack, if pack has fewer values than required, leave the remaining unchanged
template < typename T, std::size_t N, typename... U > void assign( T (&vec)[N], U&&... pack )
{ detail_::assign_helper< T, N >::assign( vec, std::forward<U>(pack)... ) ; }
constexpr struct value_initialise_tail_t {} value_initialise_tail{} ;
// assign values from the pack, if pack has fewer values than required, value initialise the remaining
template < typename T, std::size_t N, typename... U > void assign( value_initialise_tail_t, T (&vec)[N], U&&... pack )
{ detail_::missing_argument_provider< T, N, ( sizeof...(U) >= N ), U... >::assign( vec, std::forward<U>(pack)... ) ; }
int main()
{
int a[9]{} ;
const auto print_a = [&a] { for( int v : a ) std::cout << std::setw(2) << v << ' ' ; std::cout << '\n' ; };
assign( a, 1, 2, 3, 4, 5, 6, 7, 8, 9 ) ;
print_a() ; // 1 2 3 4 5 6 7 8 9
assign( a, -1, 2, -3, 4, -5, 66, 77, 88, 99, 100, -111, 212 ) ;
print_a() ; // -1 2 -3 4 -5 66 77 88 99
assign( a, 1, -2, 3, -4, 5 ) ;
print_a() ; // 1 -2 3 -4 5 66 77 88 99
assign( value_initialise_tail, a, -4, -5, -6, -7, -8 ) ;
print_a() ; // -4 -5 -6 -7 -8 0 0 0 0
assign(a) ;
print_a() ; // -4 -5 -6 -7 -8 0 0 0 0
assign( value_initialise_tail, a ) ;
print_a() ; // 0 0 0 0 0 0 0 0 0
}
|