#include <iostream>
struct foo_t
{
void bar() const { std::cout << "const!" << std::endl; }
void bar() { 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 C>
struct method_info{ using type = std::false_type; };
template<typename R, typename C, typename... P>
struct method_info<R(C::*)(P...) const>
{
using type = std::true_type;
using return_type = R;
using parameter_types = std::tuple<P...>;
};
template<typename R, typename C, typename... P>
struct method_info<R(C::*)(P...)>
{
using type = std::true_type;
using return_type = R;
using parameter_types = std::tuple<P...>;
};
static constexpr auto ptr = get_const_method_ptr(&foo_t::bar);
using test1 = decltype(ptr);
using test2 = decltype(get_const_method_ptr(ptr));
using test3 = decltype(get_const_method_ptr(&foo_t::bar));
static_assert(!std::is_same_v<test1, test2>, "wrong"); // warum sind die typen nicht gleich???
static_assert(std::is_same_v<test2, test3>, "wrong"); // die sind gleich
// warum kann ich hier aus dem ptr nicht die richtige method_info deducten??? (ich lande in der false_type implementation) liegt das an test1 != test2?
using with_ptr = method_info<decltype(ptr)>::type;
static_assert(std::is_same_v<with_ptr, std::false_type>, "wrong");
// so geht es - aber ich wuerde eben gerne auf das weitere get_const_method_ptr verzichten (weniger boilerplate in meinem Echt-Fall)
using wrapped_ptr = method_info<decltype(get_const_method_ptr(ptr))>;
static_assert(std::is_same_v<wrapped_ptr::type, std::true_type>, "wrong");
int main()
{
// obwohl test1 != test2 komme ich hier an die richtige Methode
test1 t1 = &foo_t::bar; // die const-variante wird aufgerufen
test2 t2 = &foo_t::bar; // die const-variante wird aufgerufen
test3 t3 = &foo_t::bar; // die const-variante wird aufgerufen
auto t4 = get_non_const_method_ptr(&foo_t::bar); // non-const
foo_t f;
(&f->*t1)();
(&f->*t2)();
(&f->*t3)();
(&f->*t4)();
return 0;
}