public
Last active

Demonstration of Mathias Gaunard's overloaded function object technique. See also https://gist.github.com/3779508

  • Download Gist
lambda-overload.cpp
C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
// Copyright Dave Abrahams 2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 
template<class...Fs> struct overloaded;
 
template<class F1, class...Fs>
struct overloaded<F1, Fs...> : F1, overloaded<Fs...>::type
{
typedef overloaded type;
 
overloaded(F1 head, Fs...tail)
: F1(head),
overloaded<Fs...>::type(tail...)
{}
using F1::operator();
using overloaded<Fs...>::type::operator();
};
 
template<class F>
struct overloaded<F> : F
{
typedef F type;
using F::operator();
};
 
template<class...Fs>
typename overloaded<Fs...>::type overload(Fs...x)
{ return overloaded<Fs...>(x...); }
 
auto f = overload(
[](int x) { return x+1; },
[](char const* y) { return y + 1; },
[](int* y) { return y; });
 
int main()
{
int a = f(1);
char const* p = f("hello");
int* r = f(&a);
}

I was very impressed by http://cpp-next.com/archive/2012/09/unifying-generic-functions-and-function-objects/
and was trying to find a variadic implementation:

I ended up with:

    #include <iostream>
    template <typename T, typename ... Ts>
    struct OverloadSet : public T, public Ts...
    {
        OverloadSet(T x, Ts...xs)
            : T(x)
            , Ts(xs)... { }

        // Even specifing just one T::operator()
        // is enough to disambiguate
        using T::operator();
    };
    template <typename ... Ts>
    auto getOverloadSet(Ts ... xs) -> OverloadSet<Ts...>
    {
        return OverloadSet<Ts...>(xs...);
    }
    int main(int argc, char *argv[])
    {
        auto f = getOverloadSet(
                                []() { return 1; },
                                [](int x) { return x+1; },
                                [](double x) { return x+1.0; }
                               );
         std::cout << f()  << std::endl;
         std::cout << f(2)  << std::endl;
         std::cout << f(3.5)  << std::endl;
    };

What gets me is that this works with just one

    using T::operator();

Can you explain to me why?

Thanks.

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.