
On Mon, Jul 18, 2011 at 5:26 PM, Edward Diener <eldiener@tropicsoft.com>wrote:
On 7/17/2011 11:35 PM, Jeffrey Lee Hellrung, Jr. wrote:
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.
MPL is very clear about not globbing more than one thing as a result of a metafunction. I agree with this.
:: nod ::
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.
Actually, I'm not finding it so bad anymore. But you might do well putting it into its own separate section in the documentation.
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.
Yeah I'm not totally on board either. Another idea is to have a special, additional macro generate both metafunctions. 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".
Like I said, it depends on how you count. They're as different as the the metafunctions and metafunction classes are different. It's moot anyway if you're dropping the metafunction classes in favor of boost::mpl::quote[n]. 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.
Yeah but I'm starting to believe this duplication is inevitable.
Thirdly I do not really see where the "one way is the only right way" is best here.
I'm not saying, in general, that if there are 3 (or 4) ways to do the same thing, that one necessarily has to be the best and right way. Indeed, solution (1) is naturally possible with anything remotely like member_type_xxx, and solution (4) is naturally possible assuming has_type_xxx accepts Boost.MPL lambda expressions. Really the only argument I can make for (4) over (1) is it arguably has a more natural nesting order and it doesn't require any additional constructs beyond has_ queries. As for (2) (say)...I think I would be more accepting of it there was just *one* generic component that wrapped metafunctions into nullary type metafunctions, rather than 10 as there are currently, and framed the use of nullary type metafunctions (i.e., fully lazy MPL) in a more general context. By itself, I don't see the value it provides. Specifically, I'm missing... 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.
...this :( You're trading "typename ... ::type" (and these are only necessary in the deeper levels of the query for solution (4) above, if you want) for mf_member_type and mf_has_whatever. See my previous email comparing the syntaxes of the various approaches (which, I admit, may have been unfair as I'm not sure if I got the other solutions right...I *think* I did, though). This trade does not seem to be an improvement, at least not syntactically. If you can convince me otherwise, I think, at a minimum, it will help the documentation. Side-by-side comparisons would certainly help. Speaking of which, no matter how many techniques you present to perform deeply nested type introspection (or any other task), it's important to convey to the user the pros and cons of each technique, so that they can make an informed decision. Just to reiterate, I don't feel like you've made your case (after reading the documentation) that the nullary type metafunctions are a syntactic improvement, which is their raison d'etre according to the documentation. 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 think (hypothetically) if you're the only one who wants to use a component of your library (or of any library), generally either (a) whatever documentation on the component is not doing a good job conveying its purpose, and/or only you know how to really use it; (b) you should be using something else (i.e., everyone else has it right); or (c) your needs are (highly?) specialized. In cases (b) and (c), I think I have to seriously question whether the component is appropriate for Boost. In case (a), it's at least not ready for Boost. [...] - Jeff