Class specialization for array NTTP

108 views Asked by At

I'm trying to specialize the template X for an array NTTP.

But this does not work:

template<auto& V>
struct X {
    static inline auto v = V[0];
};

template<typename T, auto N>
struct X<T (&a)[N] > {
    static inline auto v = N;
};

int main () {
    int ar[10];
    X<ar> x;
    return x.v;
}

Is that possible in the first place? Or should one use requirements / constraints for that purpose?

The errors are:

<source>:14:14: error: 'a' was not declared in this scope
   14 | struct X<T (&a)[N] > {
      |              ^
<source>: In function 'int main()':
<source>:20:9: error: the address of 'ar' is not a valid template argument because it does not have static storage duration
   20 |     X<ar> x;
      |         ^
<source>:21:14: error: request for member 'v' in 'x', which is of non-class type 'int'
   21 |     return x.v;
      |              ^
Compiler returned: 1
2

There are 2 answers

0
Jarod42 On BEST ANSWER

You have "typo" in the way to specialize (what is a)?

The specialization should look like:

template<typename T, std::size_t N, T (&a)[N]>
struct X<a> {
    static inline auto v = N;
};

And ar should have the appropriate storage duration, as the error further indicates.

Demo

6
463035818_is_not_an_ai On

As the error states, you cannot use ar as template argument because it does not have static storage duration. This is one issue.

Then you have a typo in the specialization (see this answer). However, consider whether you need to specialize at all. There is std::is_array and, as mentioned in a comment, std::size to deduce the size:

#include <type_traits>
#include <iostream>

#include <array>

template<auto& V>
struct X {
    static inline auto v = std::is_array_v<std::remove_reference_t<decltype(V)>> ? std::size(V) : V[0];
};

static constexpr int ar[10]{};

int main () {
    X<ar> x;
    std::cout << X<ar>::v;
}

Live Demo