#include <boost/type_traits/is_array.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/type_traits/remove_bounds.hpp>
#include <iostream>


using namespace boost;

struct empty {};

template <class A>
struct dimension0
{
    static A a;
    enum {e = sizeof(a[0])};
    typedef char (&type)[sizeof(A)/e];
};

template <class T>
struct eval0
{
    typedef typename T not_array;
};

template <>
struct eval0<void>
{};

template <
    std::size_t d
  , class A
>
struct legal_array_counter;

template <
    std::size_t d
  , class A
>
struct array_counter
{
    enum { legal = is_array<A>::value };

    typedef typename mpl::eval_if_c<
        !legal
      , mpl::identity<void>
      , legal_array_counter<d,A>
    >::type type;
};

template <std::size_t d, class A>
typename eval0<
    typename array_counter<d,A>::type
>::not_array dimension(A& a);

template <
    std::size_t d_
  , class A
>
struct legal_array_counter
{
    typedef typename remove_bounds<A>::type element;
    enum { d = d_ };
    typedef typename mpl::eval_if_c<
        d
      , array_counter<d-1,element>
      , dimension0<A>
    >::type type;
};

struct X
{
    operator void*() const;
    double operator[](std::size_t) const;
};

template <class X> struct whatis {};

int main()
{
    typedef X xt[1][2][3][4][5];
    xt a;
    (void)a;
    
    char a1[sizeof dimension<0>(a)] = { 0 }; // <--
    char a2[sizeof dimension<1>(a)] = { 0 };
    char a3[sizeof dimension<2>(a)] = { 0 };
    char a4[sizeof dimension<3>(a)] = { 0 };
    char a5[sizeof dimension<4>(a)] = { 0 };
#ifdef FAIL
    char a6[sizeof dimension<5>(a)] = { 0 };
#endif 

    std::cout << sizeof(a1) << ", " << sizeof(a2)
              << ", " << sizeof(a3) << ", " << sizeof(a4)
              << ", " << sizeof(a5)
              << '\n';

    return 0;
}



