1

I have an array I want to initialise as a constexpr based on template paramaters (I think this will require c++14, as I envisage the answer requiring initialiser lists as constexpr).

Lets say I have a template

template<T t>

where

 T = int[1][2][3]

now, i can extract the array sizes recursively using type_traits std::extent

what I'd like to do ultimately is generate a constexpr member with the dimensions of T as elements of myarray

std::array<int,3> myarray = {1,2,3};

I've seen what looks like a nice way to initialise an array using a variadic template ref: How to construct std::array object with initializer list?

The question is, how to generate either an initialiser list or variadic template with the dimensions of T given T?1

1
  • 1
    @R.MartinhoFernandes: I prefer to engage my brain before typing stuff in and hoping it will compile. And as I can't navigate the problem, I a) read through a lot of the internet, including stackoverflow then b), posted a clear question stating my problem as a minimum example. Is this not sufficant? Commented Oct 31, 2013 at 8:43

2 Answers 2

2

The following is a bit complicated but it should work (with C++11):

#include <array>
#include <type_traits>

template<std::size_t...> struct seq {};

template<typename,typename> struct cat;
template<std::size_t... Is, std::size_t... Js>
struct cat<seq<Is...>,seq<Js...>>
{
    using type = seq<Is...,Js...>;
};

template<typename> struct extract_seq { using type = seq<>; };
template<typename T,std::size_t N>
struct extract_seq<T[N]>
{
    using type = typename cat< seq<N>, typename extract_seq<T>::type >::type;
};

template<typename T> struct extract_type { using type = T; };
template<typename T,std::size_t N>
struct extract_type<T[N]>
  : extract_type<T>
{};

template<typename,typename> struct to_array_helper;
template<typename T, std::size_t... Is>
struct to_array_helper<T,seq<Is...>>
{
    constexpr static const std::array<T,sizeof...(Is)> value {{ Is... }};
};

template<typename T, std::size_t... Is>
constexpr const std::array<T,sizeof...(Is)>
to_array_helper<T,seq<Is...>>::value;

template<typename T>
struct to_array
  : to_array_helper<typename extract_type<T>::type,
                    typename extract_seq<T>::type>
{};

int main()
{
    auto arr = to_array< int[1][2][3] >::value;
}

Live example

Sign up to request clarification or add additional context in comments.

5 Comments

I'm not sure if I completely grasped the question (tired), but isn't something like this a bit simpler?
(Or that, might be a bit more flexible)
@DyP Nice, your version is much easier although you repeated the int in to_array<int, int[1][2][3]>. But that can be nicely integrated, see here.
Well that was partially intentional. I had something like the solution in the second comment in mind, where you can specify the return type; specifying the element type of the array somehow was a first simple step.
@DyP I see, you were going for a more general solution while I was trying to concentrate on what the OP needs. Anyways, he should have plenty of code to play with now. :)
1

I don't think you need any special future C++. This works fine in C++11:

#include <array>
#include <iostream>
#include <type_traits>

#include <prettyprint.hpp>

template <typename T>
struct Foo
{
    std::array<std::size_t, std::rank<T>::value> a;

    Foo() : Foo(X<std::rank<T>::value>(), Y<>(), Z<T>()) { }

private:
    template <unsigned int K>  struct X { };
    template <unsigned int ...I> struct Y { };
    template <typename> struct Z { };

    template <typename U, unsigned int K, unsigned int ...I>
    Foo(X<K>, Y<I...>, Z<U>)
    : Foo(X<K - 1>(),
          Y<I..., std::extent<U>::value>(),
          Z<typename std::remove_extent<U>::type>())
    { }

    template <typename U, unsigned int ...I>
    Foo(X<0>, Y<I...>, Z<U>) 
    : a { I... }
    { }
};

int main()
{
    Foo<char[4][9][1]> x;
    std::cout << x.a << std::endl;
}

Outputs:

[4, 9, 1]

3 Comments

This numerates the dimensions, but doesn't return the dimensions themselves. For instance consider T = int[7][14][13]. The desired result array contains 7 14 13
@OllieB: Oh, I see, I got thrown off by your example. Hm, maybe sticking std::extent somewhere in there fixes that. Let me think about it.
@OllieB: There, fixed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.