@Barry's answer is definitely correct and acceptable. But this requires some additions to the C ++ 14 library (which you might also be able to write yourself in C ++ 11), and generally require some good tuple - and metaprogramming fu.
Let's look at a few arguments as a "range of ranges", where the range is just a pointer and size. Scalar arguments are only size-1 range, and A<T, N> arguments are size-N ranges.
template<class T> struct Range { T const* data_; std::size_t size_; constexpr T const* begin() const noexcept { return data_; } constexpr T const* end() const noexcept { return data_ + size_; } constexpr std::size_t size() const noexcept { return size_; } }; template<class T> constexpr Range<T> as_range(T const& t) { return { &t, 1 }; } template<class T, std::size_t N> struct A; template<class T, std::size_t N> constexpr Range<T> as_range(A<T, N> const& a) { return { a.arr, N }; }
Then you can simply do a double loop on all elements of all ranges
template <typename T, size_t N> struct A { T arr[N]; // aggregate constexpr A() = default; template <typename U, typename... Us> constexpr A(U const u, Us const&... us) : arr{} { Range<T> rngs[1 + sizeof...(Us)] { as_range(u), as_range(us)... }; auto i = 0; for (auto const& r : rngs) for (auto const& elem : r) arr[i++] = elem; assert(i == N); } };
Live Example running at compile time (requires GCC> = 6.0 or Clang> = 3.4)
template <class T, size_t N> void print(A<T, N> const& a) { for (T const& t : a.arr) { std::cout << t << ' '; } std::cout << '\n'; } int main() { constexpr A<int, 3> x(1, 2, 3); constexpr A<int, 2> y(1, 2); constexpr A<int, 6> a(x, 1, 2, 3); constexpr A<int, 6> b(1, x, 2, 3); constexpr A<int, 6> c(1, 2, x, 3); constexpr A<int, 6> d(1, 2, 3, x); constexpr A<int, 6> e(x, x); constexpr A<int, 6> f(y, y, y); print(a); // 1 2 3 1 2 3 print(b); // 1 1 2 3 2 3 print(c); // 1 2 1 2 3 3 print(d); // 1 2 3 1 2 3 print(e); // 1 2 3 1 2 3 print(f); // 1 2 1 2 1 2 }