 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Hotlips Guest
|
Posted: Thu Feb 09, 2006 11:06 am Post subject: Using enable_if and is_member_function_pointer to taste a cl |
|
|
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
|
|
| Back to top |
|
 |
Alberto Ganesh Barbati Guest
|
Posted: Fri Feb 10, 2006 3:06 am Post subject: Re: Using enable_if and is_member_function_pointer to taste |
|
|
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
|
Posted: Mon Feb 13, 2006 12:06 am Post subject: Re: Using enable_if and is_member_function_pointer to taste |
|
|
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
|
Posted: Mon Feb 13, 2006 2:06 pm Post subject: Re: Using enable_if and is_member_function_pointer to taste |
|
|
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
|
Posted: Tue Feb 14, 2006 1:06 am Post subject: Re: Using enable_if and is_member_function_pointer to taste |
|
|
"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
|
Posted: Sat Feb 18, 2006 1:06 am Post subject: Re: Using enable_if and is_member_function_pointer to taste |
|
|
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 |
|
 |
|
|
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
|
|