Композиция функций в C++

Существует много впечатляющих библиотек Boost, таких как Повышение. Лямбда или Повышение. Финикс, которые имеют большое значение для превращения C++ на действительно функциональный язык. Но существует ли простой способ создать сложную функцию от каких-либо 2 или больше произвольных функций или функторов?

Если я имею: int f(int x) и int g(int x), Я хочу сделать что-то как f . g который статически генерировал бы новый функциональный объект, эквивалентный f(g(x)).

Это, кажется, возможно через различные методы, таково как обсужденные здесь. Конечно, можно объединить вызовы в цепочку к boost::lambda::bind создать составной функтор. Но есть ли что-нибудь в Повышении, которое легко позволяет Вам брать какие-либо 2 или больше функции или функциональные объекты и комбинировать их для создания единственного составного функтора, подобного тому, как Вы сделали бы это на языке как Haskell?

9
задан Channel72 15 May 2010 в 20:19
поделиться

2 ответа

Я не знаю ничего, что поддерживает желаемый синтаксис в настоящее время. Однако создать его будет несложно. Просто переопределите * для функторов (например, boost :: function <>), чтобы он возвращал составной функтор.


template < typename R1, typename R2, typename T1, typename T2 >
boost::function<R1(T2)> operator * (boost::function<R1(T2)> const& f, boost::function<R2(T2)> const& g)
{
  return boost::bind(f, boost::bind(g, _1));
}

Не тестировалось, но я подозреваю, что это близко, если не работает из коробки.

3
ответ дан 4 December 2019 в 11:40
поделиться

Шаблон для них.

template<typename T1> class FunctorOne {
    FunctorOne(T1 newt)
        : t(newt) {}
    void operator()() {
        t();
    }
    T1 t;
};
template<> class FunctorOne<void> {
    void operator()() {
    }
};
template<typename T1> class FunctorTwo {
    FunctorOne(T1 newt)
        : t(newt) {}
    void operator()() {
        t();
    }
    T1 t;
};
template<> class FunctorTwo<void> {
    void operator()() {
    }
};
FunctorOne<FunctorTwo<FunctorOne<FunctorTwo<void>>>>> strangefunctionobject(FunctorTwo(FunctorOne(FunctorTwo()));

Рекомендуется отличное использование typedefs.
Редактировать: Упс. Оказывается, вывод типов в конструкторах - отстой. Я вернусь через минуту и ​​расскажу кое-что, что действительно работает: P
Еще больше редактирования:
Если вам нужны только функторы, а не функциональноиды, вы можете просто создать новый instance, или даже просто используйте статические функции.

template<typename T1, typename T2> class FunctorOne {
public:
    static bool Call() {
        T1::Call(T2::Call());
        return true;
    }
};
template<> class FunctorOne<void, void> {
public:
    static bool Call() {
    }
};
template<typename T1> class FunctorTwo {
public:
    static bool Call() {
        T1::Call();
    }
};
template<> class FunctorTwo<void> {
public:
    static bool Call() {
    }
};

bool haicakes = FunctorOne<FunctorTwo<void>, FunctorTwo<void>>::Call();

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

1
ответ дан 4 December 2019 в 11:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: