#include <iostream>
#include <type_traits>
struct foo_t
{
void bar(int, double) const { std::cout << "const!" << std::endl; }
void bar(short, float) { std::cout << "non-const!" << std::endl; }
};
template <typename R, typename C, typename ... P>
constexpr auto get_const_method_ptr(R(C::*method)(P...) const)
{
return static_cast<decltype(method)>(method);
}
template <typename R, typename C, typename ... P>
constexpr auto get_non_const_method_ptr(R(C::*method)(P...))
{
return static_cast<decltype(method)>(method);
}
template <typename R, typename C, typename ... P>
constexpr bool is_const_method(R(C::*)(P...) const) { return true; }
template <typename R, typename C, typename ... P>
constexpr bool is_const_method(R(C::*)(P...)) { return false; }
template <typename C, typename R, typename... P>
std::tuple<P...> method_args(R(C::*)(P...)){ return std::tuple<P...>(); }
template <typename C, typename R, typename... P>
std::tuple<P...> method_args(R(C::*)(P...) const) { return std::tuple<P...>(); }
static constexpr auto bar_const_ptr = get_const_method_ptr(&foo_t::bar); // nur 1 Angabe
static_assert(std::is_same_v<decltype(bar_const_ptr), void (foo_t::* const)(int, double) const>, "wrong");
constexpr auto bar_const_is_const = is_const_method(bar_const_ptr);
static_assert(bar_const_is_const, "wrong");
using bar_const_parameter = decltype(method_args(bar_const_ptr));
static constexpr auto bar_ptr = get_non_const_method_ptr(&foo_t::bar); // nur 1 Angabe
static_assert(std::is_same_v<decltype(bar_ptr), void (foo_t::* const)(short, float)>, "wrong");
constexpr auto bar_is_const = is_const_method(bar_ptr);
static_assert(!bar_is_const, "wrong");
using bar_parameter = decltype(method_args(bar_ptr));
int main()
{
foo_t f;
(&f->*bar_const_ptr)(10, 10.10);
(&f->*bar_ptr)(1, 20.20f);
return 0;
}