Boost logo

Boost :

Subject: Re: [boost] A more convenient Variant visitation syntax
From: Thomas Heller (thom.heller_at_[hidden])
Date: 2012-04-14 12:39:32


On Sat, Apr 14, 2012 at 5:41 PM, Mathias Gaunard
<mathias.gaunard_at_[hidden]> wrote:
> On 14/04/12 17:00, Kevin Wu Won wrote:
>>
>> While Boost Variant is a wonderful library that fills a genuine hole
>> in the C++ language, it is not as nice to use as it could be.  The
>> "correct" way to unwrap a variant is to apply a static visitor, but
>> this method carries a high syntactic burden because it needs the user
>> to define a class (probably somewhere far away) just so they can
>> "switch" on the type of the object stored in the variant.
>>
>> I came up with a solution where the handler functions can be specified
>> inline with C++11 lambdas.  Here's an example:
>>
>>     boost::variant<  int, std::string>  u("hello world");
>>     int result = match(u,
>>         [](int i)                   ->  int { return i; },
>>         [](const std::string&  str) ->  int { return str.length(); });
>>
>>
>> The `match` function accepts the variant followed by the handler
>> functions.  The functions can be specified in any order.  It will fail
>> to compile if the functions do not match the types of the variant, if
>> the return types are not all the same, or if a non-unary function is
>> supplied.
>>
>> This is C++11 only because it's quite pointless without lambda
>> functions.  I've tested it with gcc 4.7.  It doesn't work on gcc 4.6,
>> which can't handle the variadic templates.
>
>
> It can be done in C++03 and expression-template-based lambdas just fine as
> well.
>
> All you need to do is generate a function object that inherits recursively
> from a set of other function objects.
>
> The function objects in question need to be either monomorphic or to be
> sufficiently constrained with SFINAE so that each operator() overload is not
> ambiguous.
>
> Unfortunately, Boost.Phoenix was never extended to support this.

I really like the idea, and i think the C++11-based solution above is
nice! I didn't have the time yet to glance through the code though ...

Phoenix didn't tackle that yet because it is a hard problem ... the
main problem is the syntax how to express which lambda is responsible
for what types. The above solution with C++11 lambdas is nice indeed!
However, what's missing is something like a "catch all" aka a
templated lambda ...
FWIW, independent of this thread I wanted to tackle that for the next
release ... I'd like to see some propositions on how such a type
based matching could be done with phoenix, which might come down to
have something like pattern matching in functional languages ... I
have no idea how to to do that yet ....


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