Boost logo

Boost :

Subject: Re: [boost] An open typeswitch using lambdas
From: Sumant Tambe (sutambe_at_[hidden])
Date: 2013-11-30 13:52:44


Great feedback so far. Thanks!

If I know what I'm talking about then,

typeswitch != overload resolution
typeswitch != static_visitor

When a programmer uses overload resolution, it's more like: "Mr. Compiler,
here are a bunch of functions named identically. Select the best one based
on the parameter I have here. Feel free to do some reasonable conversions
along the way,"

When a programmer uses a typeswitch, it's more like: "Hey typeswitch, here
are a bunch of typecases I want you to match exactly to the parameter. If
none of them match, don't bother calling any. So, no conversions, please.
If you see a default typecase (i.e., a lambda wrapped in an "otherwise"
functor) use that one if you don't find an exact match".

Example:

void func(std::string);
void func(double);

int var;
func(var) // calls func(double) as per overload resolution.

on the other hand,

match(var)(
  [](std::string) { std::cout << "Ok string\n"; },
  [](double) { std::cout << "Ok double\n"; },
  otherwise([](auto something){ std::cout << "don't know\n"; })
);

prints "don't know".

This is expected and desirable when I have my typeswitch hat on. Some may
wonder if this is a right design choice. Well, that's the point, it is a
choice. If you need good old overload resolution, the language has it and
you have an option of using boost.OverloadFunction library when needed.
(pretty cool library btw). I see no reason to duplicate that.

typeswitch is also quite different from the static_visitor because
typeswitch does not statically check if all the possible cases are handled.
boost.variant static_visitor does that. That's great when you want it. But
in the case of boost.any (also poco::dynamic_any), no compile-time solution
is possible.

In the above match example, I don't think twice if var were a boost.any. I
would naturally expect otherwise clause being called because the any has an
integer and the specific typecases don't match an int. The typeswitch
library is also applicable to polymorphic class hierarchies. The tests
(dynamic_cast) must be performed at run-time in that case.

>> The only issue I immediately see with the overload implementation is that
>> it will require special handling if someone passes in a function pointer,
>> which is a perfectly valid function object so you'd expect it to just
work
>> as a user of match. That said, support for function pointers would still
be
>> very easy to add in, it's just something that shouldn't be forgotten.

As this is not an yet another overload implementation, there is probably
less need to support function pointers. That support is already available
in boost.function_overload. Furthermore, you could simply wrap a function
pointer in lambda typecase.

>> .... This would be extremely useful for creating
>> boost::variant visitors right at the apply_visitor call-site.

Certainly. Such capability belongs in boost.variant where all the visit
cases will be enforced statically.

>> The bug is probably just worked around by using "using operator()".
>> When I was experimenting with that kind of thing, it worked just fine.

Right. Any idea how to use the using syntax with variadic parameters. I
tried the following which did not work.

template <class... Functor>
struct Foo : Functor ...
{
  using Functor::operator() ...;
};

>> You could wrap lambdas into proper function objects to work around this.

That's what the "otherwise" clause does in my implementation of match.

>> ... cannot use generic code etc

Again, the "otherwise" clause is a good place to use a generic lambda if
that's what you meant.

>> Getting a reasonable, deduced
>> return type should be easy with decltype and common_type (really,
>> apply_visitor should probably do this if it hasn't been updated to do so
>> already, using the explicit result_type instead only if it is specified,
>> and allowing the return type to be an explicit template argument to
>> apply_visitor).

Interesting! Let me think more on that a bit. As of now, anything that the
typecase lambdas return is simply tossed away.

R/ Sumant

On 30 November 2013 09:46, Matt Calabrese <rivorus_at_[hidden]> wrote:

> On Sat, Nov 30, 2013 at 5:11 AM, Mathias Gaunard <
> mathias.gaunard_at_[hidden]> wrote:
>
> > AFAIK variant doesn't require that your visitors inherit from
> >> static_visitor, just that they define the result_type typedef.
> >
> >
> Well, whatever the current requirement is specified as, it would be nice if
> this utility met that requirement. Being able to easily write variant
> visitors at the call-site is very useful. Getting a reasonable, deduced
> return type should be easy with decltype and common_type (really,
> apply_visitor should probably do this if it hasn't been updated to do so
> already, using the explicit result_type instead only if it is specified,
> and allowing the return type to be an explicit template argument to
> apply_visitor). Anything that makes variants easier to use is a great
> addition to boost, IMO.
>
> --
> -Matt Calabrese
>
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost
>


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk