Too long for a comment - what's wrong with a C++11 approach?
#include <array>
#include <cstddef>
template < std::size_t t_dim >
constexpr std::array<int, t_dim> init()
{
static_assert(false, "Unknown # of dimensions");
return {};
}
template <>
constexpr std::array<int, 2> init<2>()
{
return {1, 2};
}
template <>
constexpr std::array<int, 3> init<3>()
{
return {1, 2, 3};
}
void function()
{
std::array<int, nDim> a = init<nDim>();
}
int main()
{
function();
}
Edit: approach using local types
Edit2: Using non-type template parameter pack to simplify declaration syntax.
Edit3: Simplified (removing SFINAE was possible after storing the initialization values as non-type template arguments).
Edit4: Combined first and previous approach for even easier usage syntax and allow types which are invalid as non-type template parameter again.
Warning: black ugly template magic
#include <array>
#include <cstddef>
#include <algorithm>
#include <iostream>
#include <iterator>
constexpr std::size_t nDim = 3;
template < typename TArr >
struct stdarray_extent
{
static std::size_t const value = TArr{}.size();
};
template < bool t_if, typename T_Then, typename T_Else >
struct type_if
{
using type = T_Then;
};
template < typename T_Then, typename T_Else >
struct type_if < false, T_Then, T_Else >
{
using type = T_Else;
};
template < std::size_t t_dim, typename T, typename... TT >
struct init_
: init_ < t_dim, TT... >
{
using base = init_ < t_dim, TT... >;
static bool constexpr valid = ( stdarray_extent<T>::value == t_dim
? true : base::valid);
using type = typename type_if < stdarray_extent<T>::value == t_dim,
T, typename base::type
> :: type;
template < typename TF, typename... TTF >
static constexpr
typename std::enable_if< stdarray_extent<TF>::value == t_dim, type >::type
get(TF&& p, TTF&&... pp)
{
return p;
}
template < typename TF, typename... TTF >
static constexpr
typename std::enable_if< stdarray_extent<TF>::value != t_dim, type>::type
get(TF&& p, TTF&&... pp)
{
return base::get( std::forward<TTF>(pp)... );
}
};
template < std::size_t t_dim, typename T >
struct init_ < t_dim, T >
{
static bool constexpr valid = (stdarray_extent<T>::value == t_dim);
using type = typename type_if < stdarray_extent<T>::value == t_dim,
T,
std::array<typename T::value_type, t_dim>
> :: type;
template < typename TF >
static constexpr
typename std::enable_if< stdarray_extent<TF>::value == t_dim, type>::type
get(TF&& p)
{
return p;
}
template < typename TF >
static constexpr
typename std::enable_if< stdarray_extent<TF>::value != t_dim, type>::type
get(TF&& p)
{
return {};
}
};
template < std::size_t t_dim, typename... TT >
auto init(TT&&... pp)
-> decltype( init_<t_dim, TT...>::get(std::forward<TT>(pp)...) )
{
static_assert( init_<t_dim, TT...>::valid, "Unknown # of Dimensions" );
return init_<t_dim, TT...>::get(std::forward<TT>(pp)...);
}
void function()
{
constexpr std::size_t nDim = 3;
std::array<int, nDim> a = init<nDim>( std::array<int,2>{{1,2}},
std::array<int,3>{{3,2,1}} );
// output
std::copy( std::begin(a), std::end(a),
std::ostream_iterator<int>{std::cout, ", "} );
}
int main()
{
function();
}