Boost logo

Boost :

Subject: Re: [boost] [TTI] Review for The Type Traits Introspection library by Edward Diener **extended**
From: Jeffrey Lee Hellrung, Jr. (jeffrey.hellrung_at_[hidden])
Date: 2011-07-17 19:55:47


On Sun, Jul 17, 2011 at 2:49 PM, Edward Diener <eldiener_at_[hidden]>wrote:

> On 7/17/2011 3:21 PM, Jeffrey Lee Hellrung, Jr. wrote:
>
[...]

> The light went on finally. You want the 'type with check' idea to be
> extended to any check which can be formulated in terms of a metafunction
> rather than just a check that a typedef is the same as some other type.
>

Yep.

> That is a fruitful idea but I really have to think about that in terms of
> the syntax I have already developed. I am not saying it can not fit in to my
> current design, even most successfully.
>

I don't think it changes any syntax other than advanced usage of
has_type_xxx and eliminating the need (from what I've seen so far, anyway)
of BOOST_TTI_MEMBER_TYPE, boost::tti::valid_member_type, and the nullary
type metafunction framework.

> struct T
>> {
>> struct A
>> {
>> struct B
>> {
>> struct C
>> {
>> int x;
>> };
>> };
>> };
>> };
>>
>> Question: Does the type T::A::B exist?
>>
>> Answer:
>> BOOST_TTI_HAS_TYPE( A )
>> BOOST_TTI_HAS_TYPE( B )
>> using boost::mpl::_1;
>> has_type_A< T, has_type_B< _1> >::value
>>
>
Let's contrast the above with the solutions presently in the documentation:

// Using MEMBER_TYPE
BOOST_TTI_MEMBER_TYPE( A )
BOOST_TTI_HAS_TYPE( B )
has_type_B< typename member_type_A<T>::type >::value

// Using nullary type metafunctions
BOOST_TTI_MEMBER_TYPE( A )
BOOST_TTI_HAS_TYPE( B )
using boost::mpl::_1;
using boost::mpl::identity;
mf_has_type<
    has_type_B< _1 >,
    mf_member_type<
        member_type_A< _1 >,
        identity<T>
>
>::value

Did I get those right? I'm not sure :(

Question: Does the type T::A::B::C exist?
>>
>> Answer:
>> BOOST_TTI_HAS_TYPE( C )
>> using boost::mpl::lambda;
>> has_type_A<
>> T,
>> has_type_B<
>> _1,
>> typename lambda< has_type_C< _1> >::type
>> >
>>
>>> ::value
>>>
>>
Again, let's contrast the above with the solutions presently in the
documentation.

// Using MEMBER_TYPE
BOOST_TTI_MEMBER_TYPE( A )
BOOST_TTI_MEMBER_TYPE( B )
BOOST_TTI_HAS_TYPE( C )
has_type_C<
    typename member_type_B<
        typename member_type_A<T>::type
>::type
>::value

// Using nullary type metafunctions
BOOST_TTI_MEMBER_TYPE( A )
BOOST_TTI_MEMBER_TYPE( B )
BOOST_TTI_HAS_TYPE( C )
using boost::mpl::_1;
using boost::mpl::identity;
mf_has_type<
    has_type_C< _1 >,
    mf_member_type<
        member_type_B< _1 >,
        mf_member_type<
            member_type_A< _1 >,
            identity<T>
>
>
>::value

> Question: Does the type T::A::B::C exist and have a member data x of type
>> int?
>>
>> Answer:
>> BOOST_TTI_HAS_MEMBER_DATA( x )
>> has_type_A<
>> T,
>> has_type_B<
>> _1,
>> typename lambda< has_type_C<
>> _1,
>> typename lambda< has_member_data_x< _1, int> >::type
>> > >::type
>> >
>>
>>> ::value
>>>
>>
Last example.

// Using MEMBER_TYPE
BOOST_TTI_MEMBER_TYPE( A )
BOOST_TTI_MEMBER_TYPE( B )
BOOST_TTI_MEMBER_TYPE( C )
BOOST_TTI_HAS_MEMBER_DATA( x )
has_member_data_x<
    typename member_type_C<
        typename member_type_B<
            typename member_type_A<T>::type
>::type
>::type,
    int
>::value

// Using nullary type metafunctions
BOOST_TTI_MEMBER_TYPE( A )
BOOST_TTI_MEMBER_TYPE( B )
BOOST_TTI_MEMBER_TYPE( C )
BOOST_TTI_HAS_MEMBER_DATA( x )
using boost::mpl::_1;
using boost::mpl::identity;
mf_has_member_data<
    has_member_data_x< _1 >,
    mf_member_type<
        member_type_C< _1 >,
        mf_member_type<
            member_type_B< _1 >,
            mf_member_type<
                 member_type_A< _1 >,
                 identity<T>
>
>
>
>::value

I might be biased, but I see several advantages to my proposed solutions:
(a) Proposed solution: write the query from the top down; present solutions:
write the query from the bottom up.
(b) Proposed solution: reuse existing metafunction generation framework, no
need to learn additional constructs outside of boost::mpl::lambda (and then
only for deeply nested queries); present solution: need to learn a number of
new structures, including MEMBER_TYPE, mf_has_*, and mf_member_type.
(c) Referring to the last example above, the proposed solution actually
takes about as many non-whitespace characters (I counted 120) as the
"MEMBER_TYPE" solution (I counted 118) and far fewer than the "nullary type
metafunction" solution (I didn't bother counting, but it certainly *looks*
about 50% longer). In the first example, I think the proposed solution is
clearly the winner in terms of fewest characters. [If only we had de Bruijn
indices in Boost.MPL...]

FWIW, I had a lot more difficulty figuring out what the right queries were
in terms of the present syntax than with the proposed syntax, but then I
consider myself well-versed in Boost.MPL. I think it was actually confusing
for me that you mixed the metafunction class syntax with the metafunction
syntax in the "Using the Nullary Type Metafunctions" example :/ It took me
a while to convince myself that mtfc_member_type_CType could just as easily
have been replaced with member_type_CType<_>.

 Yes, I now understand what you are suggesting with the second template
> parameter to has_type_xxx. I need to think about this before I answer it
> fully but I do not want to let it impede what already currently exists as
> part of the library and the review so my thoughts may take some time once
> the review ends.

It is a significant change to the current interface, I agree, but (of
course) I believe it is a change in the right direction.

> But I will respond eventually. I admit I am not in love with lambda syntax
> as compared to the nullary type syntax and all those nested ::type and final
> ::value

Well, let's be fair here. The "MEMBER_TYPE" solutions have the typename ...
::type constructs as well (I know it's not your preferred solution); the
nullary type syntax has an extra mf_member_type at each level of the query
hierarchy; and I just tacked on the final ::value so I was getting a boolean
expression in the end. Present solutions have that, too.

> but certainly drilling down through 'types' in a hierarchy in the order in
> which they are viewed is an advantage.
>

Indeed.

- Jeff


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