Полиморфные функторы в std :: for_each

Я пытаюсь использовать алгоритм 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); }

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

Дэйв

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
0
3 591
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Вы можете использовать функциональные адаптеры (и их прокладки) от 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.

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

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

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

хороший ответ, мне неясно из его примера, но если вектор содержит целые числа, разве ему также не нужно привязать «этот указатель» к этому mem_fun?

Evan Teran 20.10.2008 21:29

Нет, потому что указатель this будет передан в качестве аргумента функцией for_each. Указатели функций-членов будут обрабатывать виртуальный поиск.

coppro 20.10.2008 23:09

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

Dave Hillier 15.09.2015 13:09

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

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

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

Похоже, вы могли бы извлечь выгоду из Boost :: Function.

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

Основываясь на ответе @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.

Ответ принят как подходящий

Здесь вам может помочь tr1 :: ref - он предназначен для использования в качестве справочной оболочки, чтобы вы могли передавать обычные объекты по ссылке в объекты привязки или функции (даже абстрактные) по ссылкам на стандартные алгоритмы.

// 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.

Похоже, я реализовал в FunctorAdapter нечто очень похожее на reference_wrapper, которое возвращает tr1 :: ref.

Dave Hillier 21.10.2008 14:13

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