Boost logo

Boost :

Subject: Re: [boost] [TTI] Review for The Type Traits Introspection library by Edward Diener **extended**
From: Edward Diener (eldiener_at_[hidden])
Date: 2011-07-18 20:26:56


On 7/17/2011 11:35 PM, Jeffrey Lee Hellrung, Jr. wrote:
> On Sun, Jul 17, 2011 at 6:23 PM, Edward Diener<eldiener_at_[hidden]>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.

MPL is very clear about not globbing more than one thing as a result of
a metafunction. I agree with this.

> Indeed, MEMBER_TYPE is probably implemented in terms of HAS_TYPE,
> and likewise for their corresponding metafunctions, right?

Yes.

> 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?

Yes.

>
> 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

I understand this but I am not enamoured of your syntax. Let me think
about it.

>
> 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.

We have a different philosophy about this.

First of all there are really three solutions, with your suggestion
added to the two I already had. Your 2) and 3) above are hardly 'different".

Secondly MEMBER_TYPE can be used in any scenario where a nested type has
to be passed in a TTI metafunction where it may not exist. This includes
as a type in member function and member data expressions in TTI. I do
hear you when you say you want HAS_TYPE to also serve the purpose which
MEMBER_TYPE has now so as not to have to duplicate HAS_TYPE and
MEMBER_TYPE functionality.

Thirdly I do not really see where the "one way is the only right way" is
best here.

Finally, My previous two techniques, macro metafunctions and nullary
type metafunctions, are generalized ways to use TTI where the latter is
merely a syntactical improvement over the former for people like me who
don't like to have to grab the nested "::type" in metaprogramming
constructs all the time. Obviously the macor metafunctions are not going
to go away as they are the core of TTI. If nobody wants to use the
nullary metafunctions except me that is fine but I see no harm in
keeping them in the library

> 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?

An interesting idea.

>
> 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.

I agree. I am not saying your improvement to has_type is no valuable. I
am simply saying that the rest of TTI is still necessary in my opinion
for other reasons. But I will think about HAS_TYPE and MEMBER_TYPE
further to see if I can not combine them wih your extended idea about
HAS_TYPE.

Eddie


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