Boost logo

Boost :

Subject: Re: [boost] [local] Help for the Alternatives section
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2011-05-08 13:06:09


On Sun, May 8, 2011 at 11:22 AM, Mathias Gaunard
<mathias.gaunard_at_[hidden]> wrote:
> On 08/05/2011 16:04, Lorenzo Caminiti wrote:
>
>>> auto /* or the real type */ l = overload(l1, l2);
>>
>> Does Boost already have a functor overloader like overload() above?
>
> I do not think so.
>
>
>
>> template<typename F0, typename F1, typename F2 = void, typename F3 = void>
>> struct overload {
>> };
>>
>> template<typename F0R, typename F0A0, typename F1R, typename F1A0>
>> struct overload<F0R (F0A0), F1R (F1A0)>  {
>>     overload(boost::function<F0R (F0A0)>  f0, boost::function<F1R (F1A0)>
>>  f1):
>>             f0_(f0), f1_(f1) {}
>>     F0R operator()(F0A0 a0) const { return f0_(a0); }
>>     F1R operator()(F1A0 a0) const { return f1_(a0); }
>> private:
>>     boost::function<F0R (F0A0)>  f0_;
>>     boost::function<F1R (F1A0)>  f1_;
>> };
>>
>> // More specializations to overload also with F2, F3, etc.
>
> The type erasure appear unnecessary, and this implementation has big
> forwarding problems.
>
>
> What about
>
> template<typename F0, typename F1>
> struct overload_t : F0, F1
> {
>    overload_t(F0 const& f0, F1 const& f1) : F0(f0), F1(f1)
>    {
>    }
>
>    using F0::operator();
>    using F1::operator();
> };
>
> template<typename F0, typename F1>
> overload_t<F0, F1> overload(F0 const& f0, F1 const& f1)
> {
>    return overload_t<F0, F1>(f0, f1);
> }

Yes, makes sense. Using your suggestion:

#include <boost/local/function.hpp>
#include <boost/function.hpp>
#include <vector>
#include <algorithm>
#include <iostream>
#include <string>

namespace boost { namespace local { namespace function {

template<typename F0, typename F1, typename F2 = void, typename F3 = void>
struct overloaded {};

// Specialization for 2 functions.

template<typename F0, typename F1>
struct overloaded<F0, F1>: F0, F1 {
    overloaded(F0 const& f0, F1 const& f1):
            F0(f0), F1(f1) {}
    using F0::operator(); using F1::operator();
};

template<typename F0, typename F1>
overloaded< boost::function<F0>, boost::function<F1> >
overload(
      boost::local::aux::function<F0> const& f0
    , boost::local::aux::function<F1> const& f1
) {
    return overloaded< boost::function<F0>, boost::function<F1> >(f0, f1);
}

// Specialization for 3 functions.

template<typename F0, typename F1, typename F2>
struct overloaded<F0, F1, F2>: F0, F1, F2 {
    overloaded(F0 const& f0, F1 const& f1, F2 const& f2):
            F0(f0), F1(f1), F2(f2) {}
    using F0::operator(); using F1::operator(); using F2::operator();
};

template<typename F0, typename F1, typename F2>
overloaded< boost::function<F0>, boost::function<F1>, boost::function<F2> >
overload(
      boost::local::aux::function<F0> const& f0
    , boost::local::aux::function<F1> const& f1
    , boost::local::aux::function<F2> const& f2
) {
    return overloaded< boost::function<F0>, boost::function<F1>,
            boost::function<F2> >(f0, f1, f2);
}

// More specializations for more functions...

}}} // namespace boost::local::function

// More specializations to overload also with F2, F3, etc.

int main() {
    char sep = '\n';

    void BOOST_LOCAL_FUNCTION_PARAMS(const double& item, const bind& sep) {
        std::cout << item << sep;
    } BOOST_LOCAL_FUNCTION_NAME(print_double)

    void BOOST_LOCAL_FUNCTION_PARAMS(const std::string& item, const bind& sep) {
        std::cout << item << sep;
    } BOOST_LOCAL_FUNCTION_NAME(print_string)

    void BOOST_LOCAL_FUNCTION_PARAMS(const char& item, const bind& sep) {
        std::cout << item << sep;
    } BOOST_LOCAL_FUNCTION_NAME(print_char)

    boost::local::function::overloaded<
          boost::function< void (const double&) >
        , boost::function< void (const std::string&) >
        , boost::function< void (const char&) >
> print = boost::local::function::overload(
            print_double, print_string, print_char);

    std::vector<double> d(2);
    d[0] = 1.2; d[1] = 3.4;
    std::for_each(d.begin(), d.end(), print);

    std::vector<std::string> s(3);
    s[0] = "ab"; s[1] = "cd"; s[2] = "ef";
    std::for_each(s.begin(), s.end(), print);

    char c[4] = {'x', 'y', 'z', 'w'};
    std::for_each(c, c + 4, print);

    return 0;
}

> Function pointers will have to be dealt with specially, though.

This is not an issue for Boost.Local. If overload() and overloaded<>
where to be added to Boost.Function instead, this case should be
handled. I will make a note of this in Boost.Local docs rationale.
Thanks a lot.

On a separate note, Boost.Local does not allow to name a local
function after an operator. Would that ever be useful?

-- 
Lorenzo

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