I was trying to select a member fn
based on some constexpr
value. I then tried to call the selected function, but I was getting errors about how I am calling member fn
with incorrect syntax.
error: must use '.*' or '->*' to call pointer-to-member function in
'S::SelectedGetter<&S::fn1, &S::fn2>::fn (...)', e.g. '(... ->*
S::SelectedGetter<&S::fn1, &S::fn2>::fn) (...)'
18 | return SelectedGetter<&S::fn1, &S::fn2>::fn();
I tried to call it "properly" but failed. In the end I am using std::invoke
, but I wonder if this can be done without std::invoke
, using just "raw" C++ syntax.
#include <algorithm>
#include <type_traits>
static constexpr int number = 18;
struct S
{
using GetterFn = uint32_t(S::*)() const;
uint32_t fn1()const {
return 47;
}
uint32_t fn2() const {
return 8472;
}
template <GetterFn Getter1, GetterFn Getter2>
struct SelectedGetter
{
static constexpr GetterFn fn = (number < 11) ? Getter1 : Getter2;
};
uint32_t f() {
return std::invoke((SelectedGetter<&S::fn1, &S::fn2>::fn), this);
}
};
int main()
{
return S{}.f() % 100;
}
godbolt link
Note: I am fine with C++20 solutions, for example if some concept
s magic can help...
The std::invoke function in the C++ standard library is usually used to call a functor with parameters. std::function<void(int)> func = ...; // same as func(42) std::invoke(func, 42);
std::invoke( f, args... ) is a slight generalization of typing f(args...) that also handles a few additional cases. Something callable includes a function pointer or reference, a member function pointer, an object with an operator() , or a pointer to member data.
You can use pointers to member functions in the same manner as pointers to functions. You can compare pointers to member functions, assign values to them, and use them to call member functions.
the constructor is the first function which get called. and we can access the this pointer via constructor for the first time. if we are able to get the this pointer before constructor call (may be via malloc which will not call constructor at all), we can call member function even before constructor call.
You can call it like normal member function pointer call. The correct syntax would be
return ((*this).*SelectedGetter<&S::fn1, &S::fn2>::fn)();
or
return (this->*SelectedGetter<&S::fn1, &S::fn2>::fn)();
(See a demo)
Side notes:
f
are const
, also you could make it also uint32_t f() const
SelectedGetter
with a variable template (since c++14), and now you need less-typingIt will look like
// variable template
template<GetterFn Getter1, GetterFn Getter2>
static constexpr auto fn = (number < 11) ? Getter1 : Getter2;
uint32_t f() const {
return (this->*fn<&S::fn1, &S::fn2>)();
}
(See a demo)
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