On Wed, Jan 7, 2015 at 10:48 AM, Peter Dimov
Matt Calabrese wrote:
The main limitation of this approach is that overloads must copy/move the passed-in function objects. I.E. there is no known tie_overloads that would be able to exhibit the same behavior.
Hmm. If you had a reference_wrapper<F> which SFINAEd its operator() on whether F::operator() compiles, could you not then pack those reference wrappers into an overloads object?
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. On the plus side, I've never actually found the lack of a tie_overloads to be a problem, since in times that I've personally wanted it it's been easy to manually make a reference-semantic function object at the call-site via lambdas. The main difficulty is that this just can't be done automatically inside of generic code, so the value-semantics of the function object passing sometimes bleeds out to the user a little bit in generic code (the user just needs to be aware the function objects are copied/moved in). In practice this isn't much of a problem since standard library algorithms take function objects by value anyway and so people are familiar with those semantics.
And on another note, even if we had the overloads() function template, it would still make sense to me to have something like match( ... ) that is just an alias for apply_visitor( overloads( ... ) ). I would even make it a member, in which case it would probably be more properly called 'apply'. :-)
True. There is also one thing that I do like about match -- it's possible to make one that requires an /exact/ match (I.E. in places where you want to handle each case individually and don't want overload resolution, more similar to a type switch). So both match (generalized for the n-ary case) and overloads still seem useful in different scenarios. I know another booster on this list has implemented this, though I don't think it's been posted. -- -Matt Calabrese