Помощник для перегруженного указателя на функцию-член

Я хочу иметь "более приятную" операцию приведения к указателю на метод.

Дан класс с перегруженными функциями-членами и шаблоном, который ест все виды указателей и объектов-членов и просто вызывает их.

class A
{
    public:
        void Do( int i ) { std::cout << "Hallo with int " << i << std::endl;}
        void Do( float f ) { std::cout << "and with float " << f << std::endl;}
        void Do( std::string s ) { std::cout << "also with string " << s << std::endl;}
};

    template <typename OBJECT, typename METHOD, typename ... PARMS>
void Call( OBJECT& obj, METHOD m, PARMS ... parms)
{
    std::cout << __PRETTY_FUNCTION__ << std::endl;

    (obj.*m)(parms...);
}

Теперь, если я хочу использовать Call шаблон, я должен вручную привести указатель, чтобы получить правильную версию перегруженных функций, таких как:

   Call( a, static_cast< void(A::*)(int)>( &A::Do ), 1);
   Call( a, static_cast< void(A::*)(float)>( &A::Do ), 8.88);
   Call( a, static_cast< void(A::*)(std::string)>( &A::Do ), "Willi");

Поэтому я хотел бы сделать приведение более легким для чтения и получил этот вспомогательный класс:

template <typename > class Cast;

template < typename RET, typename ... ARGS >
class Cast< RET(ARGS...)>
{
    public:
        template < typename OBJ >
            static auto From( RET(OBJ::*ptr)(ARGS...))-> RET(OBJ::*)(ARGS...)
            {
                return ptr;
            }
};

и может использовать его как:

    Call( a, Cast<void(int)>::From( &A::Do ), 100);
    Call( a, Cast<void(float)>::From( &A::Do ), 4.46);
    Call( a, Cast<void(std::string)>::From( &A::Do ),"Check it");

Q: Возможно ли сделать мой класс Cast функция шаблона, чтобы получить синтаксис для вызова приведения немного проще? Я хочу что-то, что можно назвать так:

Call( a, Cast<void(std::string)>(  &A::Do ), "Yeeeaaa!");

Но я не могу найти способ написать шаблонную функцию таким образом, потому что любая специализация, которую я написал, не была разрешена.

Разрешен любой вид с ++. Если C++17 дает новый путь, дайте мне знать!

Почему я не могу использовать параметры лямбды внутри функции вызова:

Мой реальный код должен только регистрировать указатели, но не вызывать указатели напрямую. Таким образом, функция приведения также должна работать с:

Register( a, Cast<void(int)>::From( &A::Do ));

1 ответ

Решение

Вам не нужно выделять аргументы и тип результата, чтобы снова присоединиться к ним. Просто объявите указатель на тип функции:

template <typename F, typename C>
auto Cast(F (C::*ptr)) {
    return ptr;    
}

Ваш желаемый синтаксис работает:

Call(a, Cast<void(std::string)>(&A::Do), "Yeeeaaa!");
Другие вопросы по тегам