6

I'm trying to devise a way for the compiler to deduce the size of an array passed as a non-type template parameter.

I can make the template work if I explicitly pass the array size as a third template parameter, but that opens the technique to errors.

Can anyone think of a way of doing this. The code below doesn't compile, but it gives an idea of what I'm trying to achieve.

// Compile time deduction of array size.
template <typename T, const size_t SIZE>
char(&array_size(T(&array)[SIZE]))[SIZE];

#define ARRAY_SIZE(x) (sizeof(array_size(x)))

template <typename T, T BEGIN[]>
struct Test
{
  enum
  {
    SIZE = ARRAY_SIZE(BEGIN)
  };
};

int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

int main()
{
  Test<int, a> test;

  return 0;
}

[EDIT] I forgot to point out that the solution must also be C++03 compatible.

JWellbelove
  • 121
  • 2
  • 6
  • 1
    Look to `std::array` for inspiration. – Bathsheba Jan 17 '18 at 08:34
  • Possible duplicate of [Template Parameter with implicit array size](https://stackoverflow.com/questions/48241440/template-parameter-with-implicit-array-size/48241786#48241786) – xskxzr Jan 17 '18 at 08:39

2 Answers2

5

Simply

template <typename T, std::size_t N>
constexpr std::size_t array_size(const T(&)[N]) { return N; }

In C++17, you may do

template <auto V>
struct Test
{
    enum { SIZE = array_size(*V) };
};

and

Test<&a> test;

Demo

Before, you may do a more verbose

template <typename T, T t>
struct Test
{
    enum { SIZE = array_size(*t) };
};

and

Test<decltype(&a), &a> test;

Demo (works with gcc but not clang :-/)

Version which also works with clang:

template <typename T, std::size_t N>
constexpr std::integral_constant<std::size_t, N> array_size(const T(&)[N]) { return {}; }

template <typename T, T V>
struct Test
{
    enum { SIZE = decltype(array_size(*std::declval<T>()))::value };
};

Demo

Jarod42
  • 203,559
  • 14
  • 181
  • 302
-1

C++11 introduced extent in type_traits

#include <type_traits>
std::extent<decltype(a)>::value

which evaluates to the array size of the template argument. See http://en.cppreference.com/w/cpp/types/extent

silverclaw
  • 182
  • 3
  • 8