
On Sat, Jul 16, 2011 at 7:58 PM, Jeffrey Lee Hellrung, Jr. < jeffrey.hellrung@gmail.com> 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