
On Sun, Jul 17, 2011 at 6:23 PM, Edward Diener <eldiener@tropicsoft.com>wrote:
On 7/17/2011 7:55 PM, Jeffrey Lee Hellrung, Jr. wrote:
[...]
I think you are still missing what MEMBER_TYPE is used for in other contexts. This is when you need to supply a type whose type depends on some unknown T and is nested to some depth, and the type may or may not exist. In this case using complicated logic checking on whether or not HAS_TYPE exists becomes difficult. Now I grant you I may be able to build a better MEMBER_TYPE based on your idea above, and I will look into it.
Hmmm..very true, I guess something like that could and will come in handy. The use case I'm thinking of is typedef typename boost::mpl::eval_if< has_type_value_type<T>, get_type_value_type<T>, boost::mpl::identity< some_default_value_type >
::type value_type;
I think one of the things I don't like about the current setup is that there are separate HAS_TYPE and MEMBER_TYPE macros, and hence separate metafunctions, and I'd imagine implementation-wise they largely do the same thing. Indeed, MEMBER_TYPE is probably implemented in terms of HAS_TYPE, and likewise for their corresponding metafunctions, right? If I want to do both "has" queries and "get" queries, then I have to invoke both HAS_TYPE and MEMBER_TYPE macros. I guess I *could* use valid_member_type< typename member_type_xxx<T>::type > to implement has_type_xxx<T>, is that correct? I also don't think the *name* MEMBER_TYPE / member_type_xxx really conveys well what this macro / metafunction combination does; I don't have any alternatives at the moment. This might not be a good idea, but maybe it could lead a better alternative. What if we added a nested template get to has_type_xxx that was a unary metafunction? The semantics could be has_type_xxx<T>::template get<>::type => equivalent to T::xxx (and errors if a nested type with no such name exists) has_type_xxx<T>::template get<U>::type => if T has a nested type named xxx, evaluates to xxx, else evaluates to U Also despite your feeling that the mullary type metafunctions should go away
they still, in my mind, are valuable as an alternate syntax to the macro metafunctions even with your has_type extension idea.
[...]
I still feel that if I add your idea it will be added as an addition and not as a complete replacement of anything else. My reasoning is that not everyone is as knoweldgable about MPL and as comfortable with lambda expressions as you are.
That would make 3 or 4 ways (depending on how you count it) to do the same thing (deeply nested type introspection): 1) the solution described in "Nested Types" using (only) MEMBER_TYPE / member_type_xxx; 2) the solution described in "Using Nullary Type Metafunctions" using TTI metafunctions; 3) the solution described in "Using Nullary Type Metafunctions" using TTI metafunction classes; and 4) the proposed new solution using Boost.MPL lambda expression predicates within the has_type_xxx queries. I think, as a general rule, if you have 3 or 4 ways to do the same thing, you're asking for confusion. I see potential value in being able to extract the nested types "softly" *something like* what MEMBER_TYPE does now, but I do find solutions 1, 2, and 3 at least as complicated as 4 for doing purely introspection queries on deeply nested types. I'm afraid neither of us, however, are a good judge of the learning effort any of the above 4 techniques require :/ I wonder if others can share their thoughts on this...? Regarding your desire to keep the nullary type metafunctions...shouldn't one be able to turn *any* metafunction into a "nullary type metafunction" in a generic fashion, similar to how boost::mpl::quote[n] can turn any metafunction into a metafunction class? I would think providing such a generic component would be more useful (and, ultimately, less work, less documentation, and less maintenance) than providing a specialized TTI nullary type metafunction for each TTI metafunction category. What do you think about adding such a component to Boost.MPL? Regarding others' knowledge of Boost.MPL, I think we should keep in mind that we're squabbling (well...I'm squabbling) about an advanced (in my opinion) use of TTI, and the amount of Boost.MPL knowledge one needs to effectively use TTI in this way is, I think, relatively small (placeholder expressions + boost::mpl::lambda). I think the learning curve would be relatively shallow if given a couple of examples. And you typically only need boost::mpl::lambda if you're introspecting 2 levels deep. - Jeff