LINUX.ORG.RU

Передача метода как параметра


0

1

Есть функция, принимающая на аргумент функцию, зависящую от целого числа:

double f( double (*g) (int x) );

Есть метод g, зависящий от целого числа x:

double classname::g( int x );

Как его передать в функцию f? При попытке передать как f(g) компилятор ругается.



Последнее исправление: Gorthad (всего исправлений: 2)

Капитанский ответ: объявить classname::g() статическим.

Извращённый ответ: никак. Даже если завернуть classname::g() в адаптер, который выставит наружу указатель double(*)(int), то f() никак не сможет по этому указателю догадаться, что ей следует где-то найти объект classname, который надо передать как this той функции. Особенно если ей передадут не classname::g(), а какую-то bar(), которая вообще ничей не метод.

ilammy ★★★
()

И вдогонку — если предполагается использовать C++11 — то пользуя std::bind можно наколхозить очень даже OK-простой и читаемый код в данном случае.

one_more_hokum ★★★
()
Ответ на: комментарий от one_more_hokum

Большое спасибо! Как всегда, выручаете :)

Gorthad
() автор топика
Ответ на: комментарий от one_more_hokum

Сам туда иди. thread_to_member_thunk() принимает void* и делает предположения относительно того, что там лежит. Я тоже могу написать такую double f(double(*g)(int x)), которая считает, что ей передали не double(*)(int x), а указатель на структурку, где лежит double(classname::*)(int x) и classname*. Но ведь если ей передать просто указатель на функцию, то она сломается.

ilammy ★★★
()
Ответ на: комментарий от one_more_hokum

А посмотреть сигнатуру CreateThread не судьба?

И что я там должен увидеть?

#include <iostream>

double f(double(*g)(int))
{
    std::cout << g(5);
    return 0;
}

class A {
public:
    double g(int x)
    {
        return 3 * x * x;
    }
};

class B {
public:
    B(int m) : m_m(m) {}

    double g(int x)
    {
        return -7 - x * m;
    }

private:
    int m_m;
};

double g(int x)
{
    return 2 * x;
}

int main()
{
    A x;
    B y(1);

    f(g);
    f(/* WTF 1 ? */(A::g, x));
    f(/* WTF 2 ? */(B::g, y));
}

Что должно быть на месте WTF, чтобы мне вывело 10, 75 и –12?

ilammy ★★★
()
Последнее исправление: ilammy (всего исправлений: 1)

Если есть доступ к f, переопредели ее

double f(std::function<double(int)> g)

Ну или сделай шаблон функции даже.

Если доступа нет, то нормальных способов просто нет. Методу нужно откуда-то брать this. Можно сделать пару костылей, но работать с ними нужно будет очень аккуратно. Тот костыль, который выше посоветовали тебе не подходит вообще.

anonymous
()

Если перекладывать на Си, то твоя задача звучит так

Есть функция, принимающая на аргумент функцию, зависящую от целого числа:

double f( double (*g) (int x) );
Есть функция g, зависящая от указателя на структуру classname и целого числа x:
double g( classname_t *self, int x );
Как ее передать в функцию f? При попытке передать как f(g) компилятор ругается.

Может так тебе станет понятно, в чем, собственно, проблема. В отсутствии «объекта», метод которого нужно вызывать. std::function + std::bind/лямбды решат твою проблему. Но для этого нужно менять f.

anonymous
()

Это все гребанное сишное наследие. Используй не указатели на функции, а шаблоны, function, bind и лямбды...

anonymous
()
Ответ на: комментарий от ilammy

Даже если завернуть classname::g() в адаптер, который выставит наружу указатель double(*)(int)

А почему не

double g1(int x)
{
    classname C = new classname;
    return C.g(x)
}
...
f(g1)

думаю, можно и в лямбду при большом желании завернуть...

monk ★★★★★
()
Ответ на: комментарий от monk

Ты тут создаешь какой-то левый объект и вызываешь у него метод. Но я думаю, что по логике объект нужен какой-то конкретный, иначе хватило бы статического метода. Это не говоря уже об утечке памяти=)

Так что все-таки нужно переделать f, чтоб принимал function<int(double)> и передавать уже что угодно.

Вообще можно поизвращаться, но я бы не стал.

forCe
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.