Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

has_member

6 views
Skip to first unread message

Christof Warlich

unread,
Mar 22, 2008, 11:39:11 AM3/22/08
to
Hi,

I just found the following code that shows how to determine whether a
class has a certain member:

#include <iostream>
typedef char (&no_tag)[1];
typedef char (&yes_tag)[2];

template <typename T, void (T::*)()> struct ptmf_helper {};
template<typename T> no_tag has_member_foo_helper(...);

template<typename T>
yes_tag has_member_foo_helper(ptmf_helper<T, &T::foo>* p);

template<typename T> struct has_member_foo {
static const bool value = sizeof(has_member_foo_helper<T>(0)) ==
sizeof(yes_tag);
};

struct HasNoFoo {};
struct HasFoo {void foo();};
struct DerivedFromHasFoo: HasFoo {};

int main() {
std::cout << has_member_foo<HasNoFoo>::value << std::endl;
std::cout << has_member_foo<HasFoo>::value << std::endl;
std::cout << has_member_foo<DerivedFromHasFoo>::value << std::endl;
}

But what I'd really need is some "provides_member" functionaliy, i.e.
something that would also evaluate to true for any derived class of
class HasFoo. Anyone having an idea how this could be accomplished?

Furthermore, is anyone aware whether something like has_member and
provides_member is available in Boost? I would really miss it as part of
Boost's type_traits, but couldn't find it.

Finally, can anyone recommend a good overview on the functionality
provided by Boost, most notably with respect to template metaprogramming?

Thanks,

Christof

cour...@gmail.com

unread,
Mar 22, 2008, 12:15:49 PM3/22/08
to
On Mar 22, 4:39 pm, Christof Warlich <cwarl...@gmx.de> wrote:
> Hi,
>
> I just found the following code that shows how to determine whether a
> class has a certain member:
>
> #include <iostream>
> typedef char (&no_tag)[1];
> typedef char (&yes_tag)[2];
>
> template <typename T, void (T::*)()> struct ptmf_helper {};
> template<typename T> no_tag has_member_foo_helper(...);
>
> template<typename T>
> yes_tag has_member_foo_helper(ptmf_helper<T, &T::foo>* p);
>
> template<typename T> struct has_member_foo {
>      static const bool value = sizeof(has_member_foo_helper<T>(0)) ==
>                                sizeof(yes_tag);
>
> };
>
> struct HasNoFoo {};
> struct HasFoo {void foo();};
> struct DerivedFromHasFoo: HasFoo {};
>
> int main() {
>      std::cout << has_member_foo<HasNoFoo>::value << std::endl;
>      std::cout << has_member_foo<HasFoo>::value << std::endl;
>      std::cout << has_member_foo<DerivedFromHasFoo>::value << std::endl;
>
> }
>
> But what I'd really need is some "provides_member" functionaliy, i.e.
> something that would also evaluate to true for any derived class of
> class HasFoo. Anyone having an idea how this could be accomplished?


Hi,

AFAIK, you can't in a truly generic way. Pointers to members as
template parameters don't accept any conversion. In some way or
another, you must provide the base class ( that actually declares the
member function ) as a template parameter to construct the right
function signature.

I explain everything related to member detection in this article :
http://www.codeproject.com/KB/architecture/Detector.aspx

Alexandre Courpron.

Jeff Schwab

unread,
Mar 22, 2008, 12:28:23 PM3/22/08
to
Christof Warlich wrote:
> Hi,
>
> I just found the following code that shows how to determine whether a
> class has a certain member:
>
> #include <iostream>
> typedef char (&no_tag)[1];
> typedef char (&yes_tag)[2];
>
> template <typename T, void (T::*)()> struct ptmf_helper {};
> template<typename T> no_tag has_member_foo_helper(...);
>
> template<typename T>
> yes_tag has_member_foo_helper(ptmf_helper<T, &T::foo>* p);
>
> template<typename T> struct has_member_foo {
> static const bool value = sizeof(has_member_foo_helper<T>(0)) ==
> sizeof(yes_tag);
> };
>
> struct HasNoFoo {};
> struct HasFoo {void foo();};
> struct DerivedFromHasFoo: HasFoo {};
>
> int main() {
> std::cout << has_member_foo<HasNoFoo>::value << std::endl;
> std::cout << has_member_foo<HasFoo>::value << std::endl;
> std::cout << has_member_foo<DerivedFromHasFoo>::value << std::endl;
> }
>
> But what I'd really need is some "provides_member" functionaliy, i.e.
> something that would also evaluate to true for any derived class of
> class HasFoo. Anyone having an idea how this could be accomplished?

Possibly, through some clever SFINAE, but nothing comes immediately to mind.

> Furthermore, is anyone aware whether something like has_member and
> provides_member is available in Boost? I would really miss it as part of
> Boost's type_traits, but couldn't find it.
>
> Finally, can anyone recommend a good overview on the functionality
> provided by Boost, most notably with respect to template metaprogramming?

http://www.boost-consulting.com/tmpbook/

Christof Warlich

unread,
Mar 22, 2008, 2:30:56 PM3/22/08
to
cour...@gmail.com schrieb:

> AFAIK, you can't in a truly generic way. Pointers to members as
> template parameters don't accept any conversion. In some way or
> another, you must provide the base class ( that actually declares the
> member function ) as a template parameter to construct the right
> function signature.
Ok, I understand that the prototypes of any base classes members have an
implicit this pointer of the type of the base, which makes its signature
different. Thanks for this insight. But this fact brings the idea to my
mind whether that could be worked around by always exchanging these this
pointers with some fixed pointer type and then comparing these
function prototypes? I'm just dreaming, as my limited skills in this
area currently do not allow for more.

>
> I explain everything related to member detection in this article :
> http://www.codeproject.com/KB/architecture/Detector.aspx
In any case, thanks a lot for this excellent article with its detailed
explanation and the generalization provided through the DETECTOR macros.
It's really a pity that it may not be possible to make it work for
members defined in parent classes, as it limits its use significantly.

cour...@gmail.com

unread,
Mar 22, 2008, 5:01:42 PM3/22/08
to
On Mar 22, 7:30 pm, Christof Warlich <cwarl...@gmx.de> wrote:
> courp...@gmail.com schrieb:> AFAIK, you can't in a truly generic way. Pointers to members as

> > template parameters don't accept any conversion. In some way or
> > another, you must provide the base class ( that actually declares the
> > member function ) as a template parameter to construct the right
> > function signature.
>
> Ok, I understand that the prototypes of any base classes members have an
> implicit this pointer of the type of the base, which makes its signature
> different. Thanks for this insight. But this fact brings the idea to my
> mind whether that could be worked around by always exchanging these this
>   pointers with some fixed pointer type and then comparing these
> function prototypes? I'm just dreaming, as my limited skills in this
> area currently do not allow for more.

You must use the exact signature, which includes the this pointer.
There is no escape (AFAIK).

> > I explain everything related to member detection in this article :
> >http://www.codeproject.com/KB/architecture/Detector.aspx
>
> In any case, thanks a lot for this excellent article with its detailed
> explanation and the generalization provided through the DETECTOR macros.
> It's really a pity that it may not be possible to make it work for
> members defined in parent classes, as it limits its use significantly.

Thanks.
I agree this is an important limitation.

If you have Visual C++ (7.1 or higher version) and portability isn't
an issue, you can use the __if_exists keyword which allows it :

http://msdn2.microsoft.com/en-us/library/x7wy9xh3(VS.80).aspx

Alexandre Courpron.

Christof Warlich

unread,
Mar 23, 2008, 3:36:37 AM3/23/08
to
cour...@gmail.com schrieb:

>> It's really a pity that it may not be possible to make it work for
>> members defined in parent classes, as it limits its use significantly.
>
> Thanks.
> I agree this is an important limitation.
Having slept a night over this, I came to the conclusion that it may not
be as usable as I initially thought: If it would be possible, what about
multiple, non-virtual inheritance? If the member being tested exists in
more than one base, then I need to know which one I may want to use,
which requires to know the type of that base.

>
> If you have Visual C++ (7.1 or higher version) and portability isn't
> an issue, you can use the __if_exists keyword which allows it :
>
> http://msdn2.microsoft.com/en-us/library/x7wy9xh3(VS.80).aspx
Thanks for this link. But for the reasons pointed out above, I'm quite
comfortable now with your current solution. Again many many thanks for
your valuable contribution.

Christof Warlich

unread,
Mar 23, 2008, 3:50:32 AM3/23/08
to
Jeff Schwab schrieb:

>> But what I'd really need is some "provides_member" functionaliy, i.e.
>> something that would also evaluate to true for any derived class of
>> class HasFoo. Anyone having an idea how this could be accomplished?
>
> Possibly, through some clever SFINAE, but nothing comes immediately to
> mind.

In the mean time, I doubt that it may be worth the effort to further spend
time on this issue for the reasons pointed out in my previous answer to
Alexandre.

> http://www.boost-consulting.com/tmpbook/

Thanks for this recommendation, it looks like the perfect match for my
needs as I just realize that I have taken my initial code example from a
post of one of the authors of the book, Aleksey Gurtovoy.

cour...@gmail.com

unread,
Mar 23, 2008, 8:12:17 PM3/23/08
to
On Mar 23, 8:36 am, Christof Warlich <cwarl...@gmx.de> wrote:
> courp...@gmail.com schrieb:>> It's really a pity that it may not be possible to make it work for

You're welcome.

Alexandre Courpron.

0 new messages