jeudi 31 mars 2016

A class with an array member of generic rank

Consider the following code sample:

#include <iostream>
#include <tuple>

template<typename T, std::size_t Rank, std::size_t... In>
struct help;

template<typename T, std::size_t... In>
struct help<T, 1, In...> 
{
    static constexpr auto a = std::make_tuple(In...);
    T data[std::get<0>(a)];
};

template<typename T, std::size_t... In>
struct help<T, 2, In...>
{
    static constexpr auto a = std::make_tuple(In...);
    T data[std::get<0>(a)][std::get<1>(a)];
};

template<typename T, std::size_t... In>
class foo : public help<T, sizeof...(In), In...>
{
private:
    using base = help<T, sizeof...(In), In...>;

public:
    template<typename... Tn>
    constexpr foo(Tn&&... args)
        : base{ { args... } } // constructor would only work if rank == 1
    {}
              T operator[](std::size_t i)       noexcept { return base::data[i]; }
    constexpr T operator[](std::size_t i) const noexcept { return base::data[i]; }
};

int main() 
{   
    foo<int, 6> a = {  1, 2, 3, 4, 5, 6  };

    for (std::size_t i = 0; i < 6; ++i) {
        std::cout << a[i] << " ";
    }
}  

This is as far as I got.

I'm trying to make a class, objects of which shall be constructed as foo<int, 2>; foo<int, 3, 4>; foo<int, 1, 2, 3, 4>; These objects will hold an array member respectively of type int[2]; int[3][4]; int[1][2][3][4].

My initial thinking was to make a helper template class which would specialize quite a lot (at least until an array of rank 20). That is obviously verbose, and after I get to an array of rank 2, I have no idea what the constructor for foo should be.

The constructor problem can be solved by making the class a POD (no access specifiers, etc) and construct via aggregate initialization (much like std::array does), but that goes against my work so far with the "proper inherited specialization".

I would appreciate some ideas. How would you go about doing something like this?

Aucun commentaire:

Enregistrer un commentaire