I have the following class:
#include <iostream>
template <typename T, void(*deleter)(T)>
struct MyMoveOnlyHandleType
{
void reset() { deleter(handle); }
T handle;
~MyMoveOnlyHandleType() { reset(); }
};
int main() {
{
MyMoveOnlyHandleType<int, [](int arg) {
std::cout << "Hello";
} > my_handle;
}
}
And it compiles on all three major compilers after c++17. However, I don't understand how void(*deleter)(T)
can be given as a template parameter, because ordinarily this is a function pointer.
I'm assuming that it's interpreted as a "non-type template parameter". OK. Ordinarily a "type template parameter" looks like this:
template <typename T>
And a non-type template parameter looks like this:
template <int N>
So, I assumed that the right way to do this would be to first write the type, and then write the 'identifier':
template <void (*)(int) deleter>
The void (*)(int)
would be declaring the type, and then the deleter
would be the equivalent to N
in template <int N>
.
That compiles in Clang and GCC, but not in MSVC. Is that right?
So, I assumed that the right way to do this would be to first write the type, and then write the 'identifier':
Declaring a function pointer does not follow the simple pattern of type name
. You declare a function pointer to function with void
return,int
parameter, named foo
, initialized to point to a function called bar
like this:
void (*foo)(int) = &bar;
For more readability you can use a type alias:
using func_type = void(*)(int);
func_type foo = &bar;
I'm assuming that it's interpreted as a "non-type template parameter". OK
Right.