C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Using enable_if and is_member_function_pointer to taste a cl

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Hotlips
Guest





PostPosted: Thu Feb 09, 2006 11:06 am    Post subject: Using enable_if and is_member_function_pointer to taste a cl Reply with quote



Hi
I would like to taste a class and see whether or not it has a certain
member function (h).
If it has I would like to call it, else I would like to do something
else.
I have tried using some boost stuff like enable_if and
is_member_function_pointer but I have absolutely no clue what so ever
if this is the right direction I'm going in???????

A simple example of what I intent to do is:
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits.hpp>
struct X
{
void f(){};
};

struct Y
{
void h(){};
};

// default behaviour
template <typename T, class Enable = void>
class Test
{
T t;
public:
Test(){t.f();}
};

// if the class T has a member function called h with the signature
"void ()" use this template
template <typename T>
class Test<T, typename
boost::enable_if<boost::is_member_function_pointer<T::h>::type > >
{
T t;
public:
Test(){t.h();}
};

int main()
{
Test<X> t1; // should call X::f
Test<Y> t2; // should call X::g
}

My VC++ 8.0 compiler issues some warnings and errors, looking like:
warning C4346: 'T::h' : dependent name is not a type prefix with
'typename' to indicate a type
error C2923: 'boost::is_member_function_pointer' : 'T::h' is not a
valid template type argument for parameter 'T'
error C2955: 'boost::is_member_function_pointer' : use of class
template requires template argument list

Of course I have misunderstood something, but what??? I have no clue at
all!


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Maxim Yegorushkin
Guest





PostPosted: Thu Feb 09, 2006 7:06 pm    Post subject: Re: Using enable_if and is_member_function_pointer to taste Reply with quote



Hotlips wrote:
Quote:
I would like to taste a class and see whether or not it has a certain
member function (h).

It has been answered recently. See
http://groups.google.com/group/comp.lang.c++.moderated/msg/410c7680a9b31411


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Alberto Ganesh Barbati
Guest





PostPosted: Fri Feb 10, 2006 3:06 am    Post subject: Re: Using enable_if and is_member_function_pointer to taste Reply with quote



Hotlips ha scritto:

Quote:
My VC++ 8.0 compiler issues some warnings and errors, looking like:
warning C4346: 'T::h' : dependent name is not a type prefix with
'typename' to indicate a type
error C2923: 'boost::is_member_function_pointer' : 'T::h' is not a
valid template type argument for parameter 'T'
error C2955: 'boost::is_member_function_pointer' : use of class
template requires template argument list

T::h is not a pointer to member, &T::h is.

Ganesh

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Hotlips
Guest





PostPosted: Mon Feb 13, 2006 12:06 am    Post subject: Re: Using enable_if and is_member_function_pointer to taste Reply with quote

Woooawww!
As proposed by Maxim Yegorushkin I looked into
http://groups.google.com/group/comp.lang.c++.moderated/msg/410c7680a9b31411
and found some very cryptic code that solved my problem (thanks,
Maxim!). As seen in the following I have purified it so i appears to
look like code from "C++ Templates, The Complete Guide" by Vandevoorde
and Josuttis and added some usage of boost::enable_if to select the
right template-class. A real meta programming SFINEA eye-opener for
me!!!! The next version of my database library at http://www.dtilib.dk
will contain similar code to distinct between a predefined Record class
containing a mandatory create-binding method or a anonymous record in
the form of a boost::tuple to host a row.

#include <boost/utility/enable_if.hpp>
#include <iostream>

template <typename T>
class has_foo
{
// foo member function is expected to have type void(T::*)()
template<void(T::*)()> struct wrap;

typedef char One;
typedef struct { char a[2]; } Two;

template<typename U> static One test(U*, wrap<&U::foo>* = 0);
static Two test(...);

public:
enum { value = 1 == sizeof(has_foo<T>::test((T*)0)) };
};

struct A { void zap(){std::cout << "A::zap\n";}};
struct B { void foo(){std::cout << "B::foo\n";}};

template <class T, class Enable = void>
struct Test
{
T t;
Test(){t.zap();}
};

template <class T>
struct Test<T, typename boost::enable_if<has_foo<T> >::type>
{
T t;
Test(){t.foo();}
};

void main()
{
bool b1 = has_foo<A>::value;
bool b2 = has_foo<B>::value;
Test<A> a;
Test<B> b;
}


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Maxim Yegorushkin
Guest





PostPosted: Mon Feb 13, 2006 2:06 pm    Post subject: Re: Using enable_if and is_member_function_pointer to taste Reply with quote

Hotlips wrote:
Quote:
Woooawww!
As proposed by Maxim Yegorushkin I looked into
http://groups.google.com/group/comp.lang.c++.moderated/msg/410c7680a9b31411
and found some very cryptic code that solved my problem (thanks,
Maxim!). As seen in the following I have purified it so i appears to
look like code from "C++ Templates, The Complete Guide" by Vandevoorde
and Josuttis and added some usage of boost::enable_if to select the
right template-class.

You don't need boost::enable_if here at all, it only makes it harder to
read and understand, since it's intended for overload resolution
manipulation, which is not the case here.

template <class T, bool use_foo = has_foo<T>::value>
struct Test
{
T t;
Test(){t.zap();}
};

template <class T>
struct Test<T, true>
{
T t;
Test(){t.foo();}
};


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
David Abrahams
Guest





PostPosted: Tue Feb 14, 2006 1:06 am    Post subject: Re: Using enable_if and is_member_function_pointer to taste Reply with quote

"Maxim Yegorushkin" <maxim.yegorushkin (AT) gmail (DOT) com> writes:

Quote:
You don't need boost::enable_if here at all, it only makes it harder
to read and understand, since it's intended for overload resolution
manipulation

It is also intended for the selection of partial specializations.
Says so right in the introduction. Details at:
http://www.boost.org/libs/utility/enable_if.html#htoc6

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Hotlips
Guest





PostPosted: Sat Feb 18, 2006 1:06 am    Post subject: Re: Using enable_if and is_member_function_pointer to taste Reply with quote

Maxim Yegorushkin wrote:
Quote:
template <class T, bool use_foo = has_foo<T>::value
struct Test
{
T t;
Test(){t.zap();}
};

template <class T
struct Test<T, true
{
T t;
Test(){t.foo();}
};

This code simpliefies my example, but I still have a problem with the
code: If I instantiate the
Test-template with an int-type, like
Test<int> t_i;
the compiler will vomit and tell me that the type 'T' (where T is
"int")
must be a class or namespace when followed by '::', meaning that int is
not a class.
The current class that fails to compile looks like:
template <typename T>
class has_foo
{
// foo member function is expected to have type void(T::*)()
template<void(T::*)()> struct wrap;
typedef char One;
typedef struct { char a[2]; } Two;
template<typename U> static One test(U*, wrap<&U::foo>* = 0);
static Two test(...);
public:
enum { value = 1 == sizeof(has_foo<T>::test((T*)0)) };
};

I can make specialialisations, but it will not help:

template <>
struct Test<int,false>
{
int t;
Test(){std::cout << "int type\n";}
};

because the compiler will still try to evaluate the boolean expression.
Adding a level of indirection by using boost::enable_if and also use
the specialization will help, but I'm not interested in creating
specializations for each build in type.
I think (without knowning) that adding some kind of SFINAE to the
definition

template<typename U> static One test(U*, wrap<&U::foo>* = 0);

will help, but I'm not sure how this should be done!
Any suggestions???

Best Regards,
Kristian Lippert, Danish Technological Institute


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.