Вызовите указатель на функцию-член, переданную в функцию

Я передаю указатель на функцию-член в функцию шаблона. Что-то вроде этого,

    Foo bar; /* bar.baz(...) is a function */
    auto pnt = bar.baz;

    passMmbFunc<...,decltype(pnt)>(...,pnt);

Соответствующие части passMmbFunc выглядят так:

   template <..., typename D>
   void map(..., D func) {
     ...
     auto ret = func(someVal);
     ...
   }

Я предположил, что синтаксис вызова указателя на функцию-член такой же, как и у обычного указателя на функцию, но это не так. Я получаю следующую ошибку,

    error: must use '.*' or '->*' to call pointer-to-member function in 'func (...)', e.g. '(... ->* func) (...)'

Изнутри passMmbFunc, как мне вызвать pnt? Я знаю, что указатель на функцию-член можно вызвать, если у вас есть под рукой объект соответствующего класса. Но поскольку я передаю его как параметр, это не так. Итак, есть ли способ вызвать указатель на функцию-член, если у вас есть только указатель и нет объекта?


person Community    schedule 26.04.2015    source источник
comment
Вы сделали неверное предположение.   -  person dtech    schedule 26.04.2015
comment
Синтаксис сбивает вас с толку, потому что (как было сказано в предыдущем комментарии) вы слишком много предполагали. Вы не можете вызвать указатель на нестатическую функцию-член без объекта, и синтаксис гарантирует это.   -  person PaulMcKenzie    schedule 26.04.2015
comment
Что будет означать вызов функции-члена, такой как size() или to_string() или что-то еще, без экземпляра соответствующего класса?   -  person Mat    schedule 26.04.2015
comment
Ах я вижу. Вызов функции не имеет смысла вне контекста объекта. Так что это будет работать, если функция-член будет статической?   -  person    schedule 26.04.2015
comment
@sguzman Если функция статическая, то да, вы можете вызвать ее без экземпляра объекта.   -  person PaulMcKenzie    schedule 26.04.2015
comment
@ddriver Оказывается, мой вопрос дублируется. Я отмечу это как таковое.   -  person    schedule 26.04.2015


Ответы (1)


Функция указателя на член должна быть вызвана для объекта — она не может работать как отдельная функция. Отсюда ваша ошибка. baz нужно вызывать с некоторым Foo, используя синтаксис .* или ->*:

auto ptr_to_mem = &Foo::baz;
Foo f, *pf;

ptr_to_mem();        // error
(f.*ptr_to_mem)();   // ok
(pf->*ptr_to_mem()); // ok

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

auto pnt = std::bind(&Foo::baz, bar);
pnt(); // this is the equivalent of bar.baz();

Одним из возможных источников путаницы является то, что auto pnt = bar.baz; на самом деле будет делать в Python именно то, что вам нужно. Только не на С++.

person Barry    schedule 26.04.2015
comment
Вы имеете в виду The way to do this in C++(11) - person texasbruce; 26.04.2015
comment
Я бы сказал, что к настоящему времени С++ 11 устарел и достаточно поддерживается, чтобы его можно было считать неявным. - person dtech; 26.04.2015
comment
Я не думаю, что С++ 11 неявно включен большинством компиляторов, поскольку вам всегда нужно передавать std=c++11 - person texasbruce; 26.04.2015