Unfortunately, no, because at that point you've "flattened" the operator() to having all template parameters. Overload resolution would no longer be able to produce better or worse matches when one or more of the passed-in function objects are callable. For instance, if you pass in tie_overloads( [](int a) {}, [](auto a) ) to apply_visitor, if the variant contained an "int" then the function call would actually be ambiguous rather than preferring the int overload since both overloads are callable and now just have template parameters as arguments. I've put a lot of thought (on/off for years) into trying to come up with a tie_overloads that actually works precisely as an overload set and I'm reasonably certain that it cannot be done, but I am unable to say that for certain.
Also, additionally, the Fit library provides the `fit::conditional` which
find
the first match(whereas `fit::match` finds the best match). So by the nature
of how it works, it can be used even when the functions are flattened. So if
you wanted to use references you could do this instead:
apply_visitor( fit::conditional(
std::ref([](A & a){ cout << "it's a A!"; }),
std::ref([](B & b){ cout << "oh, a B!"; }),
std::ref([](C & c){ cout << "ah yes, a C!"; }),
std::ref([](auto & d){ cout << "a default!"; })
), v);
Of course the semantics are different. Ultimately, `fit::conditional` is
designed for overloading with conditional constraints like this:
#define IF(...) typename std::enable_if<(__VA_ARGS__), int>::type = 0
apply_visitor( fit::conditional(
[](auto & range, IF( is_range