Вопрос

Я пытаюсь использовать алгоритм stl for_each без распространения шаблонов по всему моему коду.std::for_each хочет создать экземпляр класса MyFunctor по значению, но не может, поскольку он абстрактный.Я создал класс адаптера функтора, который передает указатель по кругу, а затем разыменовывает его при необходимости.

Мой Вопрос:

Есть ли у STL или Boost уже такой класс адаптера?Я не хочу изобретать велосипед заново!

 struct MyFunctor  {
     virtual ~MyFunctor() {}
     virtual void operator()(int a) = 0; 
 }

 namespace {
     template<typename FunctorType, typename OperandType> struct
 FunctorAdapter
     {
         FunctorAdapter(FunctorType* functor) : mFunctor(functor) {}
         void operator()(OperandType& subject)
         {
             (*mFunctor)(subject);
         }

         FunctorType* mFunctor;
     }; }

 void applyToAll(MyFunctor &f) {
     FunctorHelper<MyFunctor, int> tmp(&f);
     std::for_each(myvector.begin(), myvector.end(), tmp); }

Ваше здоровье,

Дэйв

Это было полезно?

Решение

tr1::ref может помочь вам здесь --- это должна быть ссылочная оболочка, чтобы вы могли передавать обычные объекты по ссылке на объекты bind или function (даже абстрактные) по ссылке на стандартные алгоритмы.

// requires TR1 support from your compiler / standard library implementation
#include <functional>

void applyToAll(MyFunctor &f) {
    std::for_each(
        myvector.begin(), 
        myvector.end(), 
        std::tr1::ref(f) 
    ); 
}

Однако обратите ВНИМАНИЕ, что компиляторы без поддержки decltype мочь отклоните передачу ссылки на абстрактный тип...таким образом, этот код может не скомпилироваться, пока вы не получите поддержку C ++ 0x.

Другие советы

Вы могли бы использовать функциональные адаптеры (и их прокладки) из functional.

#include <functional>

using namespace std;
for_each( vec.begin(), vec.end(), :mem_fun_ptr( &MyClass::f ) );

Если ваш контейнер содержит указатели на объекты, используйте mem_fun_ptr, иначе используйте mem_fun.Рядом с ними находятся оболочки для функций-членов, которые принимают 1 аргумент: mem_fun1_ptr и mem_fun1.

@Эван:действительно, вы могли бы вызвать функцию-член с одним и тем же аргументом для каждого объекта.Первый аргумент в mem_fun1 обертки - это this указатель, второй - это аргумент функции-члена:

for_each( vec.begin(), vec.end(), bind2nd( mem_fun_ptr( &MyClass::f ), 1 ) );

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

почему бы не использовать BOOST_FOREACH?

http://www.boost.org/doc/libs/1_35_0/doc/html/foreach.html

Похоже, вы могли бы извлечь выгоду из Повышение:: Функция.

Если я правильно помню, это тоже библиотека только для заголовков, так что с ней легко работать.

Как насчет того, чтобы забыть обо всем переносе указателя функтора и вместо этого использовать bind(functor_pointer,mem_fun1(&MyFunctor::operator()); как функтор?таким образом, вам не нужно беспокоиться об управлении копией каким-либо образом.

Основываясь на ответе @xtofl , поскольку массив содержит указатели int, а не "this", я думаю, что правильное заклинание

class MyClass
{
  virtual void process(int number) = 0;
};
MyClass *instance = ...;

for_each( vec.begin(), vec.end(), binder1st(instance, mem_fun_ptr(&MyClass::process) );

Единственное отличие от кода @xtofl - это binder1st, а не binder2nd.binder2nd позволяет вам передавать один и тот же номер различным указателям "this".binder1st позволяет вам передавать различные числа одному указателю "this".

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top