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 00:56:34


On Sat, Jul 16, 2011 at 7:58 PM, Jeffrey Lee Hellrung, Jr. <
jeffrey.hellrung_at_[hidden]> wrote:
[...]

> * I don't see a compelling use case for "has type with check", where
> "check" checks if the type is the same as some given type. I would think it
> would be more useful for "check" to evaluate some Boost.MPL metafunction
> (and the old behavior is arguably clearer now: boost::is_same< U,
> boost::mpl::_1 >), and then you can roll this functionality into the "no
> check" TTI metafunction by defaulting the MPL metafunction template
> parameter to boost::mpl::always< boost::true_type > (or similar). Indeed, I
> *think* this would remove the need for BOOST_TTI_MEMBER_TYPE for the use
> case you present (see below).
>
[...]

I wanted to elaborate on this idea to see if, indeed, I can solve the same
problems outlined in the sections "Nested Types" and "Using the Nullary Type
Metafunctions" with little additional syntactic burden.

Concretely, I'm proposing that

BOOST_TTI_HAS_TYPE( name )

generates a metafunction has_type_'name' such that

has_type_'name'<T>::value == true iff T has a nested 'name' type
has_type_'name'<T,P>::value == true iff T has a nested 'name' type *and*
boost::mpl::apply1< P, T::'name' >::type::value == true

Now, let's suppose the proposed type structure in the section "Nested
Types", which I've slightly modified for convenience:

struct T { struct A { struct B { struct C { struct X { }; }; }; }; };

Let's also suppose

BOOST_TTI_HAS_TYPE( A )
BOOST_TTI_HAS_TYPE( B )
BOOST_TTI_HAS_TYPE( C )
BOOST_TTI_HAS_TYPE( X )

First, let me create a metafunction has_type_TABCX to "drill down" to
T::A::B::C::X; I would equate has_TABCX to the MyFindType typedef in the
"Nested Types" section.

using boost::mpl::_1;
using boost::mpl::always;
using boost::mpl::lambda;
using boost::mpl::protect;
using boost::mpl::true_;

template< class P = always< true_ > >
struct has_type_TABCX
    : has_type_A<
          T,
          has_type_B<
              _1,
              typename lambda< has_type_C<
                  _1,
                  typename lambda< has_type_X<
                      _1,
                      protect< typename lambda<P>::type >
> >::type
> >::type
>
>
{ };

Unfortunately, I haven't tested the above, so I'm not 100% certain the above
is correct...but I think it is :) I threw the extra protect in there to
prevent unintended substitutions if P is a bind-but-not-placeholder
expression. I'll note that de Bruijn indices [1] would make the above a
little bit cleaner, but we're stuck with traditional lambda placeholders in
Boost.MPL.

Okay, first challenge: Does T::A::B::C::X exist?

has_type_TABCX<>::value

Second challenge: Does T::A::B::C::X exist and does it have a static member
data called MyData of type int?

BOOST_TTI_HAS_STATIC_MEMBER_DATA( MyData )

using boost::is_same;

has_type_TABCX<
    has_static_member_data_MyData<
        _1,
        typename lambda< is_same< int, _1 > >::type
>
>::value

I'm satisfied enough with the above usage to believe that
BOOST_TTI_MEMBER_TYPE and boost::tti::valid_member_type are not really
necessary, as I don't see them offering a significant syntactical
advantage. That is, assuming I got my syntax above correct :/ Eddie, what
are your thoughts? I certainly might've made a mistake, and there might be
cases that BOOST_TTI_MEMBER_TYPE + boost::tti::valid_member_type address but
where the above strategy fails, I don't know...

I'll investigate the use case(s) given in the section "Using the Nullary
Type Metafunctions" in a separate post.

- Jeff

[1] http://en.wikipedia.org/wiki/De_Bruijn_index


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