We implement a system that passes callbacks to object-instance member-functions. This works nicely, see the code below. The problem is that the current state of the implementation handles only non-const member functions.
The code below compiles and demonstrates that the system is working. As soon as the /* const */
is included, it no longer compiles.
The error messages are localized not English, but the first message is 'incomplete type'.
Logically, a call to a const member-function should be not more constrained than a call to a non-const member-function, so it seems that the basic goal is sensible. It is clear that the type of a const-member differs from that of a non-const member. The problem is that we do not find a way to express to the compiler that the code is also valid for const members.
Where and how in the shown WrapP can we express that a const is acceptable? Is it possible to define a single template that accepts both, const and non-const, member functions?
#include <algorithm>
#include <functional>
#include <iostream>
using std::cout;
using std::endl;
template <auto F>
struct WrapP;
template <typename T, typename R, typename ... Args, R(T::* F)(Args...)>
struct WrapP<F> {
T* obj_;
WrapP(T* instance) : obj_(instance) {}
auto operator()(Args... args) const {
return (obj_->*F)(args...);
}
};
struct foo {
// Const below is needed, but could not be activated.
auto bar(double) /* const */ -> int {
return 314; };
};
int main() {
foo x;
// Create a functor for foo::bar
WrapP<&foo::bar> fp{ &x };
// Call the functor.
std::cout << fp( 3.14159265 ) << std::endl;
return 0;
}
If you want to specialize WrapP
for a const
member function, you need to specify that:
template <typename T, typename R, typename ... Args, R(T::* F)(Args...) const>
struct WrapP<F> { // ^___^
// ...
};
As far as I'm aware, there isn't a way to allow for either const or non-const member function pointers in a template parameter list, so you'll have to write separate specializations for those cases.