Boost logo

Boost :

From: Aleksey Gurtovoy (alexy_at_[hidden])
Date: 2001-11-26 22:09:38


> Assuming the comment refers to the names type_is and value_is , the
> intent, of course, is let_type_be<...> and let_value_be<...> , but
> those are just too awkward to type, methinks. Or maybe not, on second
> thought. Hmm.

It is! For instance, consider stuffing a type_list by a dozen of integer
values (boost::mpl has value_list for that, but let's ignore it for the sake
of the example); with the names you propose, it will be something like this:

    typedef type_list<
        let_value_be<int,1>, let_value_be<int,7>, let_value_be<int,5>,
        let_value_be<int,2>, let_value_be<int,4>, let_value_be<int,8>,
        let_value_be<int,9>, let_value_be<int,2>, let_value_be<int,0>,
        let_value_be<int,3>, let_value_be<int,9>, let_value_be<int,1>
> values;

IMO, there is too much visual clutter here, especially if you consider how
little information the above declaration carries. Or, for example, here is a
compile-time 'for' loop:

    for_loop< let_value_be<int,1>, less_than< mpl::_1, let_value_be<int,1>
>, next<mpl::_1>
        , /* first statement */
        , /* function */
>

Personally, I find the above much less readable than current

    for_loop< int_t<1>, less_than< mpl::_1, int_t<1> >, next<mpl::_1>
        , /* first statement */
        , /* function */
>

> For my purposes, I would like the value wrapper (whatever name boost
> ultimately gives it) to handle all the integral types for which the
> language permits non-type template arguments. I have use for unsigned
> and signed ints of various sizes, as well as for bools, of course, and
> would strongly prefer that a single value wrapper handle them
> all.

In principle, I agree. I guess the only reason boost::mpl doesn't have it is
because I never needed more than two of such wrappers - one for int (int_t)
and another one for bool (bool_t). But, as I noted above, the genericity of
a single value wrapper is also its weak side - the template is much more
cumbersome to use, especially in contexts where one ideally would like to
write just an integer constant - 1, 10 or whatever - if the language has
allowed it. Just as an example of how inconvenient this might be - at some
point boost::mpl::int_t<> was called int_value<>, and I changed the name
_mainly_ because even the 9/1 characters ratio (9 "ballast"/ 1-2 informative
ones) was too much.

> The alternative seems to be lots of value wrappers, one per type,
> and I'm not fond of such proliferation.

Me too. But do you always care what underlying type - short, int or long -
is used to keep your loop counter, if all you want to do is to iterate from
0 to 10? I don't, and in such cases I don't want to write any of those
let_value_be<short,10>, let_value_be<int,10>, or let_value_be<long,0>
instead of simple int_t<10>. Yes, a library should provide a generic wrapper
along the lines you suggest, but a shorter notation for everyday usage is
also required.

> In this context, I find it useful for the value wrapper to encompass
> the type wrapper (by inheritance or by aggregation, it doesn't matter
> to me) so that, if need be, I can inquire as to the wrapped value's
> type. This, however, appears to conflict with other implementations.
> Some seem not to address this at all, while others seem to prefer that
> the wrapper's reported type (::type) be that of the wrapper itself.

Yes, the latter is what boost::mpl does. It's important to be able to treat
those int_t<>, bool_t<>, etc. "objects" as compile-time nullary functions,
which means supporting the "type" interface in the way you've described
(int_t<N>::type == int_t<N>). As for wrapped value's type - I think it
should be exposed under exactly that name: "value_type" :).

Hmm, I think I will add this to mpl, and re-define 'int_t<>' in terms of it
too:

    template<typename T, T N>
    struct integral_t
    {
        BOOST_STATIC_CONSTANT(T, value = N);
        typedef T value_type;
        typedef integral_t<N> type;

        // increment/decrement support
        typedef integral_t<N + 1> next;
        typedef integral_t<N - 1> prior;

        // default ctor, conversion operator, etc..
    };

> Thus, there are a few issues beyond naming (as important as that is)
> that ought be discussed, in my opinion, at least briefly.

Yes, and thanks for raising them!

Aleksey


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