Reputation: 300
I want to do something like this:
struct S
{
void mf() {};
template <auto f>
void func()
{
f();
}
};
int main()
{
S x;
x.func<x.mf>();
}
However, these are the errors:
error: no matching function for call to 'S::func<x.S::mf>()'`
note: candidate: 'template<auto f> void S::func()'
note: template argument deduction/substitution failed:
error: could not convert 'x.S::mf' from '<unresolved overloaded function type>' to 'void (S::*)()'
I am not sure I understand what I am doing wrong.
Why is x.mf
not resolved since I already instantiated x
? And how do I make this work?
Upvotes: 1
Views: 1478
Reputation: 32847
Why is
x.mf
not resolved since I already instantiatedx
?
Because it is not a valid syntax. There you need to mention the member function by operator &
, meaning you should have
x.func<&S::mf>();
// ^^^^^^^^
So that the template parameter will be deduced to a corresponding member function pointer. That is void(S::*)()
.
How do I make this work?
The second problem is, the function call f()
should have been a call through a member function pointer. This is different than the normal function call.
The traditional way of calling the member function pointer with the instance is
(this->*f)();
However, since c++17 this is more convenient way using more generic liberary function, so calledstd::invoke
from <functional>
header.
Meaning you could do more readable call through a member function pointer like.
#include <functional> // std::invoke
template <auto f>
void func()
{
std::invoke(f, this);
}
Upvotes: 1
Reputation: 16925
x.mf
is not a type but a member-function pointer.
We must pass it as a parameter.
Here is your modified example (not certain about what you want to do).
#include <iostream>
struct S
{
int i=123;
void mf () { std::cout << "i=" << i << '\n'; };
template <typename f>
void func (f fnct)
{
(this->*fnct)();
}
};
int main()
{
S x{456};
x.func(&S::mf);
}
Upvotes: 1