1

I am trying to built compile time tables. I use arrays of arrays of arrays ... to do that. Unfortunately the compiler is not able to deduce template arguments of the resulting type. Is there a work around?

#include <array>

template <typename T, size_t... dims>
struct variadic_array;

template <typename T, size_t... dims>
using variadic_array_t = typename variadic_array<T, dims...>::type;

template <typename T, size_t dim>
struct variadic_array<T, dim> {
  using type = std::array<T, dim>;
};

template <typename T, size_t dim, size_t ...dims>
struct variadic_array<T, dim, dims...> {
  using type = std::array<variadic_array_t<T, dims...>, dim>;
};

template <typename T, size_t ...dims>
void foo(variadic_array_t<T, dims...>) {}

void call_foo() {
  foo(variadic_array_t<int, 3, 4>{});
}

Compilation error:

error: no matching function for call to 'foo'
  foo(variadic_array_t<int, 3, 4>{});
  ^~~
note: candidate template ignored: couldn't infer template argument 'T'
  void foo(variadic_array_t<T, dims...>) {}
     ^
apaderno
  • 28,547
  • 16
  • 75
  • 90
Denis Yaroshevskiy
  • 1,218
  • 11
  • 24

1 Answers1

1

T cannot be deduced from C<T>::type (non deducing context).

You can reverse the problem by passing simple template T and retrieve information from it:

// Helpers
template <typename T> struct is_std_array : std::false_type {};

template <typename T, std::size_t N>
struct is_std_array<std::array<T, N>> : std::true_type {};

template <typename T> struct identity { using type = T; };

// The trait
template <typename T, std::size_t...> struct variadic_array_traits;

template <typename T, std::size_t N, std::size_t ... dims>
struct variadic_array_traits<std::array<T, N>, dims...>
{
    using type =
        typename std::conditional_t<is_std_array<T>::value,
                                    variadic_array_traits<T, dims..., N>,
                                    identity<variadic_array<T, dims..., N>>>::type;    
};

// For SFINAE    
template <typename ... >
using void_t = void;

// Your method
template <typename T>
void_t<typename variadic_array_traits<T>::type>
foo(T)
{
    using variadic_array_type = typename variadic_array_traits<T>::type;
    // ...
}

Demo

Jarod42
  • 203,559
  • 14
  • 181
  • 302