Skip to content

Instantly share code, notes, and snippets.

@dabrahams
Created September 25, 2012 00:50
Show Gist options
  • Save dabrahams/3779345 to your computer and use it in GitHub Desktop.
Save dabrahams/3779345 to your computer and use it in GitHub Desktop.
Demonstration of Mathias Gaunard's overloaded function object technique. See also https://gist.github.com/3779508
// 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);
}
@tit0
Copy link

tit0 commented Aug 22, 2013

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.

@tomilov
Copy link

tomilov commented Nov 14, 2016

In generic code for unary case overload type of returning value does not match the returning type of the function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment