Passing array element to template

TL;DR upgrade your compiler, and hope that they fully implement C++20.


The problem is purely one about non-type template parameters

template<int&>
struct S;

static int i;
static int arr[42];

S<i> s1;
S<arr[0]> s2;  // ill-formed?

The static is also irrelevant, in case you're wondering.

This rule exist in C++17 [temp.arg.nontype]

For a non-type template-parameter of reference or pointer type, the value of the constant expression shall not refer to (or for a pointer type, shall not be the address of):

  • a subobject, [...]

Which got relaxed in C++20

For a non-type template-parameter of reference or pointer type, [...] the reference or pointer value shall not refer to or be the address of (respectively):

  • a temporary object,
  • a string literal object,
  • the result of a typeid expression,
  • a predefined __func__ variable, or
  • a subobject of one of the above.

As to why, I can only postulate that the standard cautiously only required a very small subset of values to avoid the possibility that it isn't implementable.


There were an answer here (which was deleted) that gave me an idea how to solve it. It's not perfect, but also not bad.

#include <iostream>
#include <vector>
#include <tuple>

using DataTransfer = std::tuple<char, int>;
using DataPool     = std::vector<DataTransfer>;

typedef struct Event
{
    DataPool dataPool;
    const char* description;
} Event;

template <Event* event, int index>
class EventTransmitter
{
    public:
    EventTransmitter()
    {
        std::cout<<(event+index)->description<<"\n";
    }
};

static Event ev1{ {{'d', 4}, {'a', 1}}, "Description 1"};
static Event ev2{ {{'g', 7}, {'b', 6}}, "Description 2"};

static Event evs[2] {
    { {{'d', 4}, {'a', 1}}, "Description 1"},
    { {{'g', 7}, {'b', 6}}, "Description 2"}
};

int main()
{
    //EventTransmitter<&ev1> e1;
    //EventTransmitter<&ev2> e2;
    
    EventTransmitter<evs, 0> e3;
    EventTransmitter<evs, 1> e4;

    return 0;
}