2

Below is a simplified template class that accept an array as a template parameter. However I have to pass also the size of the array as a parameter. I would like to deduce it automatically and to write just:

const char *TextArray[] = { "zero", "one", "two" };

Array<TextArray> a;

In the actual implementation the class knows the size of TextArray at compile time, this is required (because at compiler time it is checked and paired with other items in the class). I get correctly a compiler error if I specify the wrong size:

Array<100, TextArray> a;

Class definiton:

#include <iostream>

template <std::size_t N, const char * (&A)[N]>
class Array
{
public:
    auto getCount()
    {
        return N;
    }
    auto getAt(std::size_t n)
    {
        return A[n];
    }
};


const char *TextArray[] = { "zero", "one", "two" };

int main() {
    Array<sizeof(TextArray)/sizeof(TextArray[0]), TextArray> a;

    printf("a.getCount() is %zu\n", a.getCount());
    printf("a.getAt(1) is %s\n", a.getAt(1));
}

Output:

a.getCount() is 3

a.getAt(1) is one

A solution is to use a Macro, but I don't want to pollute the global scope. A trivial improvement is to update the class so that I write:

Array<sizeof(TextArray), TextArray> a;

Using C++17 on gcc, Visual Studio, clang

Community
  • 1
  • 1
andreaplanet
  • 731
  • 5
  • 14

1 Answers1

4

You can use auto in template parameter since C++17, e.g.

template <auto &A>
class Array
{
public:
    auto getCount()
    {
        return std::size(A); // also C++17 feature, #include <iterator>
    }
    auto getAt(std::size_t n)
    {
        return A[n];
    }
};

BTW, you'd better explicitly cast a.getCount() to unsigned to match the %u specifier.

xskxzr
  • 12,442
  • 12
  • 37
  • 77
  • Ahhh, I didn't noticed that new feature. Now I just have to wait till Visual Studio implements it, but works perfectly on gcc/clang. BTW, %zu does it. – andreaplanet Jan 14 '18 at 13:13