Reputation: 337
I think code below is self explanatory. I can easily pass static variable to template parameter and it work as expected. Using static array will cleanup code, so it look nicer, but unfortunately it doesn't compile due to error I pasted in comment. Note that it was compiled by gcc 10.2 with c++17 flag. So the question is how to pass array element to template.
#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>
class EventTransmitter
{
public:
EventTransmitter()
{
std::cout<<event.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;
//error: '& evs[0]' is not a valid template argument of
//type 'Event&' because 'evs[0]' is not a variable
return 0;
}
Upvotes: 6
Views: 802
Reputation: 337
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;
}
Upvotes: 2
Reputation: 21160
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.
Upvotes: 4