Boost logo

Boost :

Subject: Re: [boost] Phoenix review
From: Giovanni Piero Deretta (gpderetta_at_[hidden])
Date: 2008-09-26 11:53:23


On Thu, Sep 25, 2008 at 5:14 PM, Doug Gregor <dgregor_at_[hidden]> wrote:
> On Sep 25, 2008, at 9:32 AM, Joel de Guzman wrote:
>
>> Doug Gregor wrote:
>>>
>>> The alternatively, of course, is to use a syntax like:
>>> case_<1>()[cout << val("one") << '\n', cerr << val("hello")],
>>> Interestingly, catch_<exception_type>()[ ... ] uses this same syntax; why
>>> the discrepancy between case_ and catch_? Or did I miss something?
>>
>> Yeah, the discrepancy... It's one of the things I'm not quite satisfied
>> with. I do like the brackets [] but the empty parens stick out like
>> a sore thumb to me. At one point, I used the [] for the cases, changing
>> it later to the (). Fickle, ain't I?
>>
>> I'm open to suggestion. If we are to break the interface anyway,
>> I'd follow what the community wants.
>
> Personally, I don't find the extra ()'s in case_<1>() all that horrible, and
> I think it's the more regular to have all of the statements in []. That
> said, unless something *else* is breaking the interface, this isn't the
> thing that should be first to break the interface.
>

Hum, what about relaxing a little the 'C++ in C++ tag' and making
switch_ more powerfull than the builtin switch?

Instead of:

    switch_(arg1)
    [
        case_<1>(cout << val("one") << '\n'),
        case_<2>(cout << val("two") << '\n'),
        default_(cout << val("other value") << '\n')
    ]

do this:

    switch_(arg1)
    [
        case(1)[cout << val("one") << '\n'],
        case(2)[cout << val("two") << '\n'],
        default_[cout << val("other value"] << '\n')
    ]

this allows not only runtime selection of switch case values, but it
will also work with everything that is equally comparable:

    switch_(arg1)
    [
        case("one")[cout << val(1) << '\n'],
        case("two")[cout << val(2) << '\n'],
        default_[cout << val("other value"] << '\n')
    ]

which IMHO is a killer feature.

The fact that the case parameter is not a template parameter might
limit compiler optimizations unless the the compiler is good at
constant propagation, but there is a workaround:

    switch_(arg1)
    [
        case(mpl::int_<1>())[cout << val("one") << '\n'],
        case(mpl::int_<2>())[cout << val("two") << '\n'],
        default_[cout << val("other value"] << '\n')
    ]

Let's leave the ugly syntax to those that need it :)

As another extension, when visiting heterogeneous sequences (think
fusion::for_each), a switch by type would be great:

    switch_(arg1)
    [
        case(type<std::string>())[cout << val("std::string") << '\n'],
        case(type<int>()) [cout << val("int") << '\n'],
        default_[cout << val("other type"] << '\n')
    ]

(in this case switch_ would need to know about type<> because it must
not compile the not-taken branches). Even better:

    switch_(arg1)
    [
        case(type<std::string>())[cout << val("std::string") << '\n'],
        case(type<std::vector<_> >()) [cout << val("a vector of
something") << '\n'],
        default_[cout << val("other type"] << '\n')
    ]

-- 
gpd

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