Я хочу, чтобы операция «лучше» выполнялась для указателя на метод.Помощник листинга для перегруженного указателя функции элемента
Предоставлен класс с перегруженными функциями-членами и шаблоном, который ест каждый тип указателей и объектов элемента и просто вызывает их.
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");
Вопрос: Возможно ли сделать мой класс Cast
функцией шаблона, чтобы получить синтаксис для приведения вызова немного проще? Я хочу что-то, что можно назвать так:
Call(a, Cast<void(std::string)>( &A::Do), "Yeeeaaa!");
Но я не могу найти способ, чтобы написать шаблонную функцию так, потому что любой вид специализации я писал не допускалось.
Разрешены любые виды C++. Если C++ 17 дает новый способ, дайте мне знать!
Почему я не могу использовать параметры для лямбда внутри вызова функции:
Мой реальный код нужно только зарегистрировать указатели, но не называют указатели прямой. Таким образом, функция литья должна также работать с:
Register(a, Cast<void(int)>::From(&A::Do));
Я никогда не видел такой синтаксис раньше! Он работает отлично, но можете ли вы объяснить, что делает «Cast» (F (C :: * ptr))? Я не могу заменить: 'Cast (void (int) C :: *)', если F не является параметром шаблона. Поэтому я смущен этой синтаксической формой. – Klaus
Нет, это точно, что происходит. C++ просто не позволяет вам прямо писать композитный тип там, например, вы не можете объявить массив с помощью 'int [42] a;', но вы можете сделать 'using A = int [42]; A a; 'То же самое здесь:' используя F = void (int); auto Cast (F C :: *) {} 'делает то, что вы ожидаете. –
@ Klaus, это не указатель на функцию! Это общий указатель на член, любой его член. Итак, когда вы вызываете это так, вы даете ему указатель на член, имеющий тип 'void (std :: string)'. Снова - обратите внимание, нет второго набора parenthethis. Может быть, это будет более ясно, если писать без скобок вообще: 'auto Cast (F C :: * ptr)' - тот же результат. – SergeyA