
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? [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. 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? 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?
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 :) - Jeff [1] http://www.boost.org/doc/libs/1_47_0/libs/function_types/doc/html/boost_func...