Boost logo

Boost :

From: Richard Peters (R.A.Peters_at_[hidden])
Date: 2001-12-06 06:22:30


From: <nbecker_at_[hidden]>
> While you're at it, I'd like to see constant. Something like:
>

What about a more general case: a constant generator, and a unary_function
that ignores the first value but returns the generator instead? Combined
they provide the functionality of your Constant, and they are also usable as
stand-alone functors. And maybe the generator class that behaves similar to
unary_function/binary_function (doesn't it already exist?)

template<class Result>
struct generator {
    typedef Result result_type;
};

template<class Arg, class Result, class Generator>
struct unary_ignore: public unary_function<Arg, Result> {
    unary_ignore() {}
    unary_ignore(Generator thegenerator):
        generator(thegenerator) {}
    Result operator()(typename call_traits<Arg>::param_type)
    {
        return Generator();
    };
private:
    Generator generator;
};

template<class Result>
struct constant: public generator<Result> {
    constant(Result thevalue):
        value(thevalue) {}
    Result operator()()
    {
        return value;
    }
private:
    const Result value;
};

and the same for the binary_function, you could ignore one of the two
parameters:

template<class Arg1, class Arg2, class Result, class UnaryFunction>
struct binary_ignore1st: public binary_function<Arg1, Arg2, Result> {
    binary_ignore1st() {}
    binary_ignore1st(UnaryFunction thefunction):
        unaryfunction(thefunction) {}
    Result operator()(typename call_traits<Arg1>::param_type,
                      typename call_traits<Arg2>::param_type y)
    {
        return unaryfunction(y);
    }
private:
    UnaryFunction unaryfunction;
};

template<class Arg1, class Arg2, class Result, class UnaryFunction>
struct binary_ignore2nd: public binary_function<Arg1, Arg2, Result> {
    binary_ignore2st() {}
    binary_ignore2st(UnaryFunction thefunction):
        unaryfunction(thefunction) {}
    Result operator()(typename call_traits<Arg1>::param_type x,
                      typename call_traits<Arg2>::param_type)
    {
        return unaryfunction(x);
    }
private:
    UnaryFunction unaryfunction;
};

Maybe the templates could be changed to something like:

template<class Generator, class Arg, class Result = typename
Generator::result_type>
struct unary_ignore: public unary_function<Arg, Result>

template<class UnaryFunction, class Arg1, class Arg2 = typename
UnaryFunction::argument_type,
    class Result = typename UnaryFunction::result_type>
struct binary_ignore1st: public binary_function<Arg1, Arg2, Result>

but on this one, it doesn't look as sweet:

template<class UnaryFunction, class Arg2, class Arg1 = typename
UnaryFunction::argument_type,
    class Result = typename UnaryFunction::result_type>
struct binary_ignore2nd: public binary_function<Arg1, Arg2, Result>

A third option would be not to give a choice a and always use the default:

template<class Generator, class Arg>
struct unary_ignore: public unary_function<Arg, typename
Generator::result_type>

template<class UnaryFunction, class Arg1>
struct binary_ignore1st: public binary_function<Arg1, typename
UnaryFunction::argument_type, typename
    UnaryFunction::result_type>

template<class UnaryFunction, class Arg2>
struct binary_ignore2nd: public binary_function<typename
UnaryFunction::argument_type, Arg2, typename
    UnaryFunction::result_type>

I'm not an expert, so I don't really know what variant would be the best.
What do you think? Does it make any sense?

Best Regards,
Richard Peters


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk