Указатели на функции-члены C ++ и алгоритм STL - PullRequest
3 голосов
/ 20 сентября 2009

У меня есть абстрактный класс функторов, который перегружает operator () и производные объекты, которые его реализуют.

У меня есть функция (часть другого класса), которая пытается взять массив из этих классов функторов и пытается передать указатель на функцию-член в алгоритм std for_each (), вот обзор того, что я делать:

РЕДАКТИРОВАТЬ: я повторно очистил его и поместил старый маленький пример для ясности.

class A{
  operator()(x param)=0;
  operator()(y param)=0;
}

class B: public A{
  operator()(x param); //implemented
  operator()(y param);
}
...// and other derived classes from A

void ClassXYZ::function(A** aArr, size_t aSize)
{
  ...//some code here

  for(size_t i = 0; i< aSize; i++){

    A* x = aArr[i];
    for(v.begin(), v.end(), ...//need to pass pointer/functor to right operator() of x here

..//other code
}

Я пробовал несколько способов, и я не могу понять, как заставить его работать, мне нужно использовать абстрактный тип, поскольку у меня могут быть разные производные типы, но все они должны будут реализовывать один и тот же оператор () (параметр x).

Мне просто нужна функция for_each (), чтобы можно было вызывать оператор функции-члена () (param x). У меня есть другая функция, где она имеет конкретные реализации и просто передает их, и это работает. Я пытаюсь добиться подобного эффекта здесь, но без знания того, какие конкретные классы мне дают.

Что я делаю не так?

Ответы [ 4 ]

4 голосов
/ 20 сентября 2009

Вы хотите что-то подобное ...

std::for_each(
  it->second.begin(),
  it->second.end(),
  std::bind1st(std::mem_fun(&A::operator()),x)
);
3 голосов
/ 20 сентября 2009

Если я понимаю, что вы хотите сделать, в вашем фрагменте кода довольно много ошибок:

  • sizeof aArr неверно, вам нужно явно указать размер (замечено ChrisW)
  • Отсутствует спецификатор virtual в исходном объявлении operator()()
  • Не уверен, где заканчивается ваш цикл for, поскольку нет соответствующего } (я подозреваю, что его вообще не должно быть)

Вот некоторый код, который будет проходить через массив объектов A (или A) и вызывать operator() для каждого, передавая переданный аргумент в качестве параметра param:

#include <iostream>
#include <algorithm>
#include <functional>

using namespace std;

typedef double param;      // Just for concreteness

class A {
public:
    virtual void operator()(param x) = 0;
};

class B : public A {
public:
    void operator()(param x) { cerr << "This is a B!  x==" << x << ".\n"; }
};

void function(A** aArr, size_t n, param theParam) {
    void (A::*sFunc)(param x) = &A::operator();
    for_each(aArr, aArr + n, bind2nd(mem_fun(sFunc), theParam));
}

int main(int argc, char** argv) {
    A* arr[] = { new B(), new B(), new B() };

    function(arr, 3, 42.69);

    delete arr[0];
    delete arr[1];
    delete arr[2];
    return 0;
}

mem_fun() необходимо для преобразования указателя на функцию-член с одним параметром в объект-функцию с двумя параметрами; bind2nd() затем создает из этого объекта с 1 параметром функцию, которая фиксирует аргумент, предоставленный для function() в качестве 2-го аргумента. (for_each() требуется однопараметрический указатель на функцию или функциональный объект.)

РЕДАКТИРОВАТЬ: Основываясь на Ответ Алекса Тингла , я делаю вывод, что вы, возможно, хотели, чтобы function() делал много вещей с одним A полученным объектом. В этом случае вам нужно что-то вроде:

void function(A** aArr, size_t n, vector<param> const& params) {
    for (size_t i = 0; i < n; ++i) {
        void (A::*sFunc)(param x) = &A::operator();
        for_each(params.begin(), params.end(), bind1st(mem_fun(sFunc), aArr[i]));
    }
}
1 голос
/ 20 сентября 2009

Выражение "bar. * Fn" не соответствует обычному или не являющемуся членом функции указателю. Поэтому вам нужно вызвать функцию привязки (либо std :: tr1 :: bind, либо boost :: bind), чтобы получить такую ​​функцию.

0 голосов
/ 20 сентября 2009

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

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

Но мне любопытно, есть ли у кого-нибудь решение исходной проблемы без необходимости использования чисто виртуальных методов «создания функтора» в базовом классе.

...