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;
}
Arrays can be passed by reference OR by degrading to a pointer. For example, using char arr[1]; foo(char arr[]). , arr degrades to a pointer; while using char arr[1]; foo(char (&arr)[1]) , arr is passed as a reference. It's notable that the former form is often regarded as ill-formed since the dimension is lost.
C++ does not allow to pass an entire array as an argument to a function. However, You can pass a pointer to an array by specifying the array's name without an index.
A whole array cannot be passed as an argument to a function in C++. You can, however, pass a pointer to an array without an index by specifying the array's name. In C, when we pass an array to a function say fun(), it is always treated as a pointer by fun().
Arrays are always pass by reference in C. Any change made to the parameter containing the array will change the value of the original array. The ampersand used in the function prototype. To make a normal parameter into a pass by reference parameter, we use the "& param" notation.
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With