C ++ 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

1

Решение

Использовать 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<> подпись)

2

Другие решения

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

В основном, положить в гипсе вручную.

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

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

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

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

1

Вы пытаетесь преобразовать указатель на функцию-член в свободный указатель на функцию, но это не сработает. Если бы это было возможно, вы забыли 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;
}

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

0