Использование std :: function в качестве делегата в C ++ 11

Скажем, у меня есть эти 3 различные функции, на которые я могу указать:

float test1(int a, int b) {
return 7.0f;
}

struct TestClass {
float test2(int a, int b) {
return 5.0f;
}
};

struct TestClass2 {
float  test3(int a, int b) {
return 3.0f;
}
};

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

Вот моя первая попытка:

typedef std::function<float(int, int)> MyDelegate; // is this right?

int main() {
TestClass obj;
TestClass2 obj2;

MyDelegate a = test1;
MyDelegate b = std::bind(std::mem_fn(&TestClass::test2), obj); // is this right?
MyDelegate c = std::bind(std::mem_fn(&TestClass2::test3), obj2); // is this right?

return 0;
}

Идея в том, что я хочу также хранить указатель this в оболочке. Таким образом, это похоже на полностью функциональный делегат. Например, вызов ‘b (x, y)’ должен быть похож на вызов obj.test2(x, y),

Я просто не могу заставить его скомпилироваться, я, вероятно, не до конца это понимаю. Я новичок в этих библиотеках, и ошибки в VS2012 катастрофически бесполезны. Любая помощь будет оценена.

7

Решение

Вы должны сказать std::bind что делать с другими параметрами функции. Для того, чтобы сделать звонок b(x, y) делегат x а также y к двум исходным параметрам функции, вам нужно использовать заполнители из std::placeholders Пространство имен:

std::bind(&TestClass::test2, obj, std::placeholders::_1, std::placeholders::_2);

И нет необходимости std::mem_fn (это работает, хотя), так как std::bind уже обрабатывает функции-члены правильно (делая неявное this аргумент явный первый аргумент, как std::mem_fn делает).

10

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

Вам нужно предоставить 2 аргумента для std :: bind или предоставить заполнители для их предоставления
потом:

std::function<float(int, int)> c = std::bind(&TestClass2::test3, obj2, 1, 2);
c(); //returns result

ИЛИ ЖЕ

std::function<float(int, int)> c = std::bind(&TestClass2::test3, obj2, std::placeholders::_1, std::placeholders::_2);
c(1, 2); //returns result

Больше информации о std :: bind is Вот.

3

Используя визуальный компилятор C ++ (CTP 2012), я заметил, как они работают с std :: function, и предложил собственное решение для обработки функций-членов.

использование выглядит так:
http://ideone.com/v5zfDn

class Window
{
public:
void Show( int number ) const
{
//...
}

void ShowDynamic( int number ) volatile
{
//...
}
};

void ShowWindows( int param )
{
//...
}

int main()
{
Window window;

typedef mezutils::Delegate< void( int ) > Notifier;
Notifier notifier;

notifier = &ShowWindows;
notifier( 0 );

notifier = Notifier( &window, &Window::Show );
notifier( 1 );

notifier = [](int x) { /*...*/ };
notifier( 2 );

void (*funpc)(int) = func;
notifier = funpc;
notifier( 3 );

notifier = [](int arg) { printf("asd %d\r\n",arg); };
notifier(4);
return 0;
}

Класс делегата выглядит так:
http://ideone.com/DebQgR

конечно, это прототип, созданный для развлечения, но мне он нравится, потому что он понятен

2
По вопросам рекламы [email protected]