#pragma once /** * Construct an ad-hoc object with an overloaded `operator()`. * * Typically used with lambdas to construct type-matching visitors for e.g. std::variant: * ``` * std::variant var; * Visit(TOverloaded{ * [](int val) { Cerr << "int: " << val; }, * [](void* val) { Cerr << "ptr: " << val; }, * [](const TString& val) { Cerr << "str: " << val; }, * }, var); * ``` * * *** IMPORTANT NOTE (IMPLICIT ARGUMENT CONVERSIONS) *** * * Since the resulting objects use regular overloaded method resolution rules, * methods may be called by inexact matches (causing implicit casts), hence this * implementation does not guarantee exhaustiveness of cases. * * For example, the following code will compile and run by casting all values to * double: * ``` * std::variant var; * Visit(TOverloaded{ * [](double val) { Cerr << "dbl: " << val; }, * }, var); * ``` * * If cases may be ambigous or specific type-matching logic is required, * a verbose `if constexpr`-based version would be preferred: * ``` * std::variant var; * Visit([](auto&& val) { * using T = std::decay_t; * if constexpr (std::is_same_v) { * Cerr << "int: " << val; * } else if constexpr (std::is_same_v) { * Cerr << "dbl: " << val; * } else if constexpr (std::is_same_v) { * Cerr << "chr: " << val; * } else { * static_assert(TDependentFalse, "unexpected type"); * } * }, var); * ``` */ template struct TOverloaded: Fs... { using Fs::operator()...; }; template TOverloaded(Fs...) -> TOverloaded;