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 19:29:30


On 7/17/2011 10:49 PM, Jeffrey Lee Hellrung, Jr. wrote:
> On Sun, Jul 17, 2011 at 5:06 PM, Edward Diener<eldiener_at_[hidden]>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


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