Re: Call a member function only if it exists in VC++ 9
On Oct 30, 12:47 am, steinb...@gmx.com wrote:
Hello,
I need to get this thing to work under MSVC++ 9.0:
-----------------
found here:http://groups.google.de/group/comp.lang.c++.moderated/browse_thread/t...
#include <iostream>
template<class T> struct has_member_f;
template<class R, class C>
class has_member_f<R C::*> {
private:
template<R C::*> struct helper;
template<class T> static char check(helper<&T::f>*);
template<class T> static char (& check(...))[2];
public:
static const bool value = (sizeof(check<C>(0)) ==
sizeof(char));
};
namespace boost { // no dependency of boost
template <bool B, class T = void>
struct enable_if_c {
typedef T type;
};
template <>
struct enable_if_c<false, void> {};
} // namespace boost
void f() {
std::cout << "::f()" << std::endl;
}
struct caller {
template <class T>
static void f(
T& t,
typename boost::enable_if_c<
has_member_f<void (T::*)()>::value
>::type* = 0) {
t.f();
}
template <class T>
static void f(
T& t,
typename boost::enable_if_c<
!has_member_f<void (T::*)()>::value
>::type* = 0) {
::f();
}
};
// client code below
struct A { };
struct B {
void f() {
std::cout << "B::f" << std::endl;
}
};
int main() {
std::cout
<< has_member_f<void (A::*)()>::value << '\n'
<< has_member_f<void (B::*)()>::value << std::endl;
A a;
caller::f(a);
B b;
caller::f(b);}
-----------------
This is meant to call a member function only if it's defined.
Otherwise it calls the default behavior. The thing is, this behaves
fine with gcc 4, but not with VC++ 9.0.
Output GCC4:
------------
0
1
::f()
B::f
Output VC9:
-----------
0
0
::f()
::f()
VC9 supports partial specialized templates, (http://msdn.microsoft.com/
en-us/library/3967w96f.aspx), but I didn't get it to work as
expected...
Anyone any ideas?
I tried your code with M$VC 2005 and its output was similar to the
output of gcc 4.
The only thing that comes to my mind is to simplify the code a bit. I
don't have M$ VC 9 to check though.
Here is a version that uses overloading instead of enable_if along
with some other simplifications:
#include <iostream>
template<class T>
class has_member_f
{
private:
template<void(T::*)()> struct helper;
template<class U>
static char check(U*, helper<&U::f>* = 0);
static char(&check(...))[2];
public:
static const bool value = (sizeof(check(static_cast<T*>(0))) ==
sizeof(char));
};
void f()
{
std::cout << "::f()" << std::endl;
}
template<bool> struct bool_ {}; // boost::mpl::bool_
template<class T>
void do_invoke_f(T&, bool_<false>)
{
::f();
}
template<class T>
void do_invoke_f(T& t, bool_<true>)
{
t.f();
}
template<class T>
void invoke_f(T& t)
{
do_invoke_f(t, bool_<has_member_f<T>::value>());
}
// client code below
struct A {};
struct B {
void f() {
std::cout << "B::f" << std::endl;
}
};
int main() {
std::cout
<< has_member_f<A>::value << '\n'
<< has_member_f<B>::value << '\n';
A a;
invoke_f(a);
B b;
invoke_f(b);
}
--
Max
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]