I've been stumped on this for a while, and distilled a simple example of my error message. Is there some way to make this work? Am I just missing a "template" or "typename" somewhere?
#include <cstdint>
template<typename T, typename J>
struct silly
{
const void (*f)(T,J);
};
template<typename T, typename J, silly<T, J> aSilly>
struct sillier
{
const uint32_t something;
};
void dumb_func(uint32_t i, uint32_t j)
{
return;
}
constexpr silly<uint32_t, uint32_t> mySilly{ .f = dumb_func };
using silliest = sillier<uint32_t, uint32_t, mySilly>;
int main()
{
return 2;
}
g++ spits out:
g++ -std=c++2a ugh.cpp
ugh.cpp:20:51: error: invalid conversion from ‘void (*)(uint32_t, uint32_t)’ {aka ‘void (*)(unsigned int, unsigned int)’} to ‘const void (*)(unsigned int, unsigned int)’ [-fpermissive]
20 | constexpr silly<uint32_t, uint32_t> mySilly{ .f = dumb_func };
| ^~~~~~~~~
| |
| void (*)(uint32_t, uint32_t) {aka void (*)(unsigned int, unsigned int)}
ugh.cpp:20:51: error: ‘dumb_func’ is not a valid template argument of type ‘const void (*)(unsigned int, unsigned int)’ because ‘dumb_func’ is not a variable
I've tried reading through https://en.cppreference.com/w/cpp/language/template_parameters but I'm out of my template depth here. The actual use case for this has T and J being something like std::array<float, ?> and then sillier<T, J, silly<T, J>> inherits from some other more general class, and has overrides which call functions like f so that everything gets inlined into specialized functions for a given instance of silly<T, J>.
Edit:
The third template parameter of sillier
is a non-type template argument, which can only be bound to a variable, but dumb_func
is not a variable.
This explanation doesn't make sense, and in fact the code is probably fine, and the error might just be a bug as discovered and reported in this answer . The fix given below still works though.
You can make the third template parameter be a non-type template parameter of reference type.
template<typename T, typename J, silly<T, J> const & aSilly>
// ^^^^^^^
struct sillier
{
const uint32_t something;
};
Also, the member variable f
in silly
is declared as a function pointer returning a const void
type:
const void (*f)(T,J);
So you either need to remove the const
from the return type of f
, or you can change the declaration of dumb_func
to return a const void
type:
const void dumb_func(uint32_t i, uint32_t j)
{
return;
}
There doesn't seem to be any point in a const void
returning function, so I would go with the first option.
Here's a demo .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.