views:

244

answers:

2

There are a lot of impressive Boost libraries such as Boost.Lambda or Boost.Phoenix which go a long way towards making C++ into a truly functional language. But is there a straightforward way to create a composite function from any 2 or more arbitrary functions or functors?

If I have: int f(int x) and int g(int x), I want to do something like f . g which would statically generate a new function object equivalent to f(g(x)).

This seems to be possible through various techniques, such as those discussed here. Certainly, you can chain calls to boost::lambda::bind to create a composite functor. But is there anything in Boost which easily allows you to take any 2 or more functions or function objects and combine them to create a single composite functor, similar to how you would do it in a language like Haskell?

+2  A: 
Noah Roberts
Since raw functions are neither classes nor enumerations, a use like `f1 * f2` will not look for overloaded operators, though :( Will use the builtin operator and fail since it can't multiply two functions.
Johannes Schaub - litb
That's the issue of having functions as second-class citizens...
Matthieu M.
Yeah, only works with functors. You could make a utility function that casts to a boost::function to match regular functions.
Noah Roberts
A: 

Template them.

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()));

Excellent use of typedefs is recommended.
Edit: Whoops. Turns out that type inference in constructors sucks. I'll get back in a minute with something that actually works :P
Even more edit:
If you wanted just functors rather than functionoids, you could just create a new instance, or even just use static functions.

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();

This assumes that in any given function, you can handle each different signature somewhat manually. Use of decltype could help in this regard with a C++0x compiler.

DeadMG