
On 7/17/2011 10:49 PM, Jeffrey Lee Hellrung, Jr. wrote:
On Sun, Jul 17, 2011 at 5:06 PM, Edward Diener<eldiener@tropicsoft.com>wrote:
On 7/17/2011 7:02 PM, Jeffrey Lee Hellrung, Jr. wrote:
[...]
To reiterate what I had
above, I propose the following to all be equivalent:
has_member_function_xxx< Result (T::*)( Arg0, Arg1 )> has_member_function_xxx< T, Result ( Arg0, Arg1 )> // my personal preference, probably has_member_function_xxx< T, Result, boost::mpl::vector2< Arg0, Arg1> >
First and third are fine. It is what now exists for BOOST_TTI_HAS_COMP_MEMBER_**FUNCTION and BOOST_TTI_HAS_MEMBER_FUNCTION respectively.
The second, even if you like it, is unnecessary, and I also use it for BOOST_TTI_HAS_COMP_STATIC_**MEMBER_FUNCTION so I do not want to create confusion.
No, you're right, it isn't necessary. Let me point out that, strictly speaking, neither is the third, as if you want to use has_member_function_xxx in a Boost.MPL placeholder expression, I think boost::function_types::member_function_pointer [1] gives you what you need. Regarding the confusion with the syntax for querying static member functions...can you elaborate on what, exactly, would be confusing?
I meant I wanted to have a different composite syntax for member functions and static member functions.
[Also, let me point out, I *myself* have used the "I think it is unnecessary" argument to argue for the *removal* of certain constructs in TTI, so...touche!]
I'm assuming the syntax is still fair game for discussion, so, if not, I apologize. But if so, please bear with me, and let's actually look at all of our alternatives. I see 4 potential syntaxes here (let's start with non-const member functions):
has_member_function< R (T::*)( U0, U1 )> // A has_member_function< T, R ( U0, U1 )> // B has_member_function< T, R, vector2< U0, U1>, Tag> // C (Tag optional) has_member_function< member_function_pointer< vector4< R, T, U0, U1>, Tag
::type> // D (Tag optional)
B, to me, would usually be the most convenient, as it has almost no syntactic baggage. Additionally, it still allows the T parameter to be a Boost.MPL placeholder expression, which is likely the most common parameter for a placeholder expression (I'm guessing). So I think B should be included.
B is still a composite syntax because the function signature is a composite type. In that case I prefer A and will use it, because A mimics the "pointer to member function of class T" which C++ programmers are used to. C is the individual types syntax. I prefer it to D because the enclosing type comes first and it is easier for the end-user. I am only looking to implement a single composite syntax and a single individual types syntax.
The only advantage A seems to offer over B is it would be necessary to allow D. Is there some meta-information (e.g., calling conventions) that can be added to member function pointers but not function types...? If so, I guess that alone might necessitate the inclusion of A, assuming it's more convenient to specify that using the Boost.FunctionTypes Tag parameter.
I presume the original motivation for including C was to allow various parts of the query to be Boost.MPL placeholder expressions. D does allow this and requires no additional syntax to be directly supported by has_member_function other than A, but maybe it's too verbose. If you think D is too verbose, then inclusion of C is justified.
BTW, if you do has_member_function< T, R, Tag>, is it automatically interpreted as has_member_function< T, R, vector0<>, Tag>, or does it error because it tries to use Tag as a Boost.MPL sequence?
It is an error. You need to supply an empty forward sequence if you supply a tag, but if you do not supply a tag the default for the 3rd template parameter is an empty vector so it need not be supplied.
I don't know if you thought about this, so I thought I should bring it up. FWIW, I would prefer forcing the user to be more explicit, i.e., force the user to explicitly including the vector0<> or empty_sequence type to indicate an empty argument list.
By the way, how do you check for const member functions? I don't remember
seeing anything about this in the documentation. I would assume something like
has_member_function_xxx< Result (T::*)( Arg0, Arg1 ) const> has_member_function_xxx< T const, Result ( Arg0, Arg1 )> has_member_function_xxx< T const, Result, boost::mpl::vector2< Arg0, Arg1>
For the first, BOOST_TTI_HAS_COMP_MEMBER_**FUNCTION, you have it correct. For the third, BOOST_TTI_HAS_MEMBER_FUNCTION, it would be:
has_member_function_xxx< T, Result, boost::mpl::vector2< Arg0, Arg1>, boost::function_types::const_**qualified>
Yuck. Would you consider using the cv-qualification of T to determine the cv-qualification of the member function to query?
Yes I should do that. The constness of T should affect what can be found. Good point !
I could also try to combine BOOST_TTI_HAS_COMP_STATIC_**MEMBER_FUNCTION and BOOST_TTI_HAS_STATIC_MEMBER_**FUNCTION but that will be a little harder because they both begin with the enclosing type while the former follows the 'Result, boost::mpl::vector2< Arg0, Arg1>' syntax while the latter follows with the 'Result ( Arg0, Arg1 )' syntax.
Well, Result can never be a function type, so...I think you're good :)
You are correct ! Eddie