How does the "overloaded" trick for calling visit on variants in C++ actually work?

52 views Asked by At

I've seen code like the following popping up in C++17 codebases and have started using it myself:

template <class... Ts>
struct overloaded : Ts... {
    using Ts::operator()...;
};

template <class... Ts>
overloaded(Ts...)->overloaded<Ts...>;

int main()
{
    std::variant<int, std::string> var = "foo";
    std::visit(
        overloaded{
            [](int) {std::cout << "int\n"; },
            [](std::string) {std::cout << "string\n"; }
        },
        var
    );

}

and am trying to understand what overloaded is actually doing. Without using variadic templates I believe the above expands to:

template <typename T, typename U>
struct overloaded : T, U {
    using T::operator();
    using U::operator();
};

template <typename T, typename U>   // <- 
overloaded(T, U)->overloaded<T, U>; // <- what is this?

I understand the definition of struct overloaded: it is inheriting from what will be two lambdas which will have operator() defined by virtue of being lambdas and saying to use those operator()s as the function call operators of overloaded. However, I don't even know what the other two lines are in terms of the semantics of C++: they seem to be making it so you can construct a struct overloaded from arbitrary lambdas or something like that.

0

There are 0 answers