используя объект функции, хотя указатель на функцию требуется - PullRequest
0 голосов
/ 18 ноября 2011

Я должен использовать какой-то устаревший код, ожидающий указатель на функцию, скажем:

void LEGACY_CODE(int(*)(int))
{
    //...
}

Однако у меня есть функтор:

struct X
{
    Y member;       
    X(Y y) : member(y)
    {}

    int operator()(int)
    {
        //...
    }
};

Как мне изменить / обернуть класс X, чтобы LEGACY_CODE мог получить доступ к функциональности в X::operator()(int)?

Ответы [ 4 ]

1 голос
/ 18 ноября 2011

Ваш вопрос не имеет смысла. Кому оператора вы хотите позвонить?

X a, b, c;

LEGACY_CODE(???); // what -- a(), b(), or c()?

Итак, короче говоря, вы не можете. Функция-член X::operator() не является свойством только одного класса, а скорее связана с экземпляром объекта типа X.

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


Самый грубый и, возможно, небезопасный для использования обходной путь к предоставлению бесплатной функции будет выглядеть так:

X * current_X;  // ugh, a global
int dispatch(int n) { current_X->operator()(n); }

int main()
{
  X a;
  current_X = &a;
  LEGACY_CODE(dispatch);
}

Вы можете видеть, куда это идет ...

0 голосов
/ 18 ноября 2011

Поточно-ориентированная версия с ограничением, что устаревший код не вызывается с другими параметрами в потоке.

ИМХО, от глобального хранилища избавиться нельзя.

#include <boost/thread.hpp>
#include <boost/thread/tss.hpp>

class AA
    {
    public:
        AA (int i) : i_(i) {}
        void  operator()(int j) const {
            static boost::mutex m; // do not garble output
            boost::mutex::scoped_lock lock(m);
            std::cout << " got " << j << " on thread " <<  i_ << std::endl; 
            Sleep(200); } 
        int i_;
    };

// LEGACY
void legacy_code(void (*f)(int), int i) {   (*f)(i);    }

// needs some global storage through
 boost::thread_specific_ptr<AA> global_ptr;

void func_of_thread(int j)
    {
    AA *a = global_ptr.get();
    a->operator()(j);
    }

void worker(int i)
{
 global_ptr.reset(new AA(i));
 for (int j=0; j<10; j++)
     legacy_code(func_of_thread,j);
    }


int main()
    {
    boost::thread worker1(worker,1) , worker2(worker,2);
    worker1.join(); worker2.join();
    return 0;
    }
0 голосов
/ 18 ноября 2011

Вот одно решение во время компиляции.В зависимости от того, что вам нужно, это может быть слишком ограниченным решением для вас.

template<typename Func, int Param>
int wrapper(int i)
{
    static Func f(Param);
    return f(i);
}
0 голосов
/ 18 ноября 2011

Простая функция-обертка выглядит так:

int wrapperfunction(int i) {
    Functor f(params);
    return f(i);
}

Если вы хотите иметь возможность передавать параметры самому функтору, самый простой способ - использовать их для использования (brr) глобальной переменной:

Functor functorForWrapperfunction;
int wrapperfunction(int i) {
    functorForWrapperfunction(i);
}
// ...
void clientCode() {
    functorForWrapperfunction = Functor(a,b,c);
    legacyCode(wrapperfunction);
}

Вы можете обернуть его классом с помощью статического метода и статического члена, если хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...