2
votes

I am not using C++11 (otherwise I would use lambdas)

I have iterators to an input data structure and output data structure. I want to do some operations on the input data and store the result in the output. Note that the start and end types may be different (int -> float for example).

I tried to model my function after the standard algorithms and gave it the following prototype

template<class INPUT_ITR, OUTPUT_ITR>
void f(INPUT_ITR in_it, INPUT_ITR in_it_end, OUTPUT_ITR out_it, ContextStuff)

The function does many different things depending on the context. Sometimes the function only needs to use one functor, so the line of code looks like this

transform(in_it, in_it_end, out_it, Functor1());

But sometimes the function wants to use a series of functors on each data element. Is there a way I can create a chain of functors as a single functor to use in transform? The functors for the chain will be known at compile type.

For example

transform(in_it, in_it_end, out_it, CHAIN(Functor1(), Functor2()));

Performs Functor1 on *in, then Functor2 on the result, then stores in *out.

I can inherit my functors from unary_function for the solution.

1
Might just be better to make a custom functor for it. Nothing really comes to mind, but I'll bet Boost has some tricks.chris
Without C++11 it's impossible to get a functor's result type without cooperation of the functor (usually result_type). So if you want to do this all your functors will have to have a result_type typedef.Fozi
@Fozi I can inherit my functors from unary_function for the solution.Neil Kirk
Also, without C++11 most of the work you will be doing is going to be writing CHAIN macros and classes that forward various amounts of parameters.Fozi
@NeilKirk Oh ok, so only one parameter...Fozi

1 Answers

2
votes

Try this:

template<class Callable1, class Callable2>
struct Chain : public std::unary_function<
    typename Callable2::argument_type, typename Callable1::result_type>
{
    Chain(const Callable1 &f1, const Callable2 &f2) : f1(f1), f2(f2) {}

    typename Callable1::result_type operator () (
           typename Callable2::argument_type param) 
    { 
        return f1(f2(param));
    }
private:
    Callable1 f1;
    Callable2 f2;
};

template<class Callable1, class Callable2>
Chain<Callable1, Callable2> chain(const Callable1 &f1, const Callable2 &f2) {
    return Chain<Callable1, Callable2>(f1, f2);
}

The Chain class is a functor that combines two other functors. Since it's a unary_function itself you should be able to combine it further. The chain function lets you create the Chain instance without having to worry about types.

Usage example: http://ideone.com/7QpmEU