Функция-член для списка указателей - PullRequest
1 голос
/ 02 марта 2012

Спасибо за комментарии к следующим.

Class1 { debug(std::ostream&){} };
int main() {
  std::vector<Class1*> list1;
  // some work to do
}

Целевая платформа:

  • Платформа (1): Win 7x64, VS2010
  • Платформа (2): Linux x32, g ++ 4.4

В: Каким должен быть правильный способ передачи "std :: cout" в следующем выражении?

std::for_each(list1.begin(), 
              list1.end(), 
              "afunction(&Class1::debug, std::cout)");

Ранее я использовал "std :: cout" внутри функции debug (), но позже рассмотрим возможность предоставления гибкости для вывода сообщения отладки.

Редактировать: Дополнительная информация: если нужно использовать объекты функтора, как мне реализовать функтор для работы с несколькими классами (эти классы не имеют отношения, за исключением одной и той же сигнатуры функции «отладка»)?

Edit (2): Используя "std :: for_each", возможно ли уничтожить все объекты в списке list1, вызвав соответствующий деструктор для каждого класса напрямую? (например, for_each (l.begin (), l.end (), "Class :: ~ Class1");

Редактировать (3): Согласно предложенному "pmr", я делаю заявление как

std::for_each(l.begin(), 
              l.end(), 
              std::bind2nd(std::mem_fn(&Class1::debug), out) );

Он компилируется и работает правильно на платформе Linux, но не работает на VS2010, код для Class1 :: debug -

void Class1::debug(const std::ostream& out)
{ 
    out << "some text" << someVar << "some text" << std::endl; 
}

Сообщение об ошибке VS

ошибка C2678: двоичный файл «<<»: не найден оператор, который принимает левый операнд типа «const std :: ostream» (или нет допустимого преобразования) </p>

Любой кий?

[Закрыто] Теперь я реализовал перегруженный оператор << для моих классов, и использование функции печати отладки закрыто. Большое спасибо за все подсказки. </p>

Ответы [ 4 ]

1 голос
/ 02 марта 2012

Так как вы используете g ++ 4.4, вы не можете использовать лямбда-выражения, которые будут лучшим выбором (более поздние версии поддерживают их, MSVC делает то же самое).

Так что вам нужен функтор.Функтор - это функциональный объект, то есть класс (или структура), реализующий operator().Вот так:

class Debug
{
public:
     Debug(ostream& os) : _os(os)
     { }

     void operator()(Class1* instance)
     {
          // will print the pointer, replace with user code
          os << instance << endl;
     }
private:
     ostream& _os;
};

Используйте вот так:

 Debug d(cout);
 std::for_each(list1.begin(), list1.end(), d);
0 голосов
/ 02 марта 2012

C ++ 03:

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

struct Foo {
  void debug(std::ostream&) {}
};

int main()
{
  std::vector<Foo*> foos;
  std::for_each(foos.begin(), foos.end(), 
                std::bind2nd(std::mem_fun(&Foo::debug), std::cout));
  return 0;
}

Обратите внимание, что связующие устарели и boost::bind или C ++ 11 следует отдать предпочтение. Вы действительно должны получить более новый компилятор.

0 голосов
/ 02 марта 2012

Поскольку GCC не поддерживает лямбды до 4.5, о самом ясном решении не может быть и речи.

Вторым самым простым решением, когда вы хотите использовать множество универсальных алгоритмов, является Boost.Lambda http://www.boost.org/doc/libs/1_49_0/doc/html/lambda.html:

for_each(list1.begin(), list.end(), _1->debug(cout));

И, наконец, решение утомительного функтора:

class Output
{
public:
     explicit Output(ostream& ios) : os(&ios)
     {
     }

     void operator()(Class1* obj)
     {
          obj->debug(*os);
     }

private:
     ostream* os;
};
for_each(list1.begin(), list1.end(), Output(cout));

Лично я считаю, что без C ++ 11 лямбд или Boost Lambdas for_each - это боль, чем стоит. Можно также сделать простой цикл:

for (vector<Class1*>::iterator it = list1.begin(); it != end; ++it)
    (*it)->debug(cout);
0 голосов
/ 02 марта 2012

используйте лямбду вместо указателей на функции. Это особенность C ++ 11x, и вам нужно включить флаг, чтобы компилятор распознал лямбду.

   std::for_each(list1.begin(), list1.end(), [&debug, &cout]
{
// implementaion
}
);
...