С++ 11 std::function: привязка метода без конкретного экземпляра

Продолжая эту тему, я хотел бы разделить ее на другой, более конкретный вопрос. Я хочу связать функцию с помощью ChaiScript, и я могу сделать это с помощью std::function, но я не могу сообщить std::function, какую перегрузку следует использовать.

Отражение соответствующих методов:

class DLLExport Actor
{
public:
        Actor(Level* level, const String& name, Actor* parent);
        virtual ~Actor();

        void setPosition(const Real& x, const Real& y, const Real& z);
        void setPosition(const Vector3& position);
};

а затем я пытаюсь связать его так:

std::function<void(Actor*, Vector3&)> setPos = &Actor::setPosition; // <-- C2440 here.
m->add(fun(setPos), "setPosition");

Я получаю следующую ошибку:

2>..\..\ScriptingDemo\Binder.cpp(63): error C2440: 'initializing' : cannot convert from 'overloaded-function' to 'std::function<void (Actor *, Vector3 &)>' 2> No constructor could take the source type, or constructor overload resolution was ambiguous


person Ilija Boshkov    schedule 25.08.2014    source источник
comment
Это сводится к stackoverflow.com/questions/4364599/c-overloaded- указатель на метод   -  person pmr    schedule 19.01.2015


Ответы (3)


Используйте typedef для своей функции-члена:

typedef void (Actor::*set_type)(const Vector3&); // Note the syntax for a member function typedef

И используйте его для чистого static_cast для устранения перегрузки:

std::function<void(Actor&, const Vector3&)> setPos = static_cast<Actor::set_type>(&Actor::setPosition);

(обратите внимание на неявный параметр Actor& для функции-члена, явный в приведенной выше подписи std::function<>)

person quantdev    schedule 25.08.2014

указатель перегруженного метода C++.

В основном, накладываем слепок вручную.

std::function<void(Actor*, const Vector3&)> setPos((void(Actor::*)(const Vector3&))&Actor::setPosition);

Теперь почему:

Оператор = для std::function сам по себе является шаблоном и не предоставляет информации о типе для своего аргумента. Поэтому, когда вы пытаетесь присвоить его &Actor::setPosition, у компилятора нет хорошего способа выяснить, какую функцию вы запрашиваете. Введение гипса исправляет это.

Аргумент Актер* исходит из типа функции Актер::*, а не из самой сигнатуры функции.

person IdeaHat    schedule 25.08.2014

Вы пытаетесь преобразовать указатель функции-члена в указатель свободной функции, и это не сработает. Если бы это было возможно, вы бы все равно забыли const в аргументах шаблона std::function.

Однако ваше включение Actor* находится на правильном пути:

#include <iostream>
#include <functional>

struct Foo {
    void bar(int const &i) { std::cout << i; }
};

int main()
{
    using namespace std::placeholders;
    std::function<void(Foo*, int const&)> func = std::bind(&Foo::bar, _1, _2);

    Foo foo;
    func(&foo, 17);

    return 0;
}

Обратите внимание, что вам все еще нужно предоставить экземпляр для вызова метода в какой-то момент, но что вы ожидаете?

person Quentin    schedule 25.08.2014