Jump to content
  • Advertisement
Sign in to follow this  
pitoneux

boost enable_if and has_xxx mecanic ?

This topic is 2992 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi there,


I need help here to understand how enable_if could allow me to call a specialized method when a certain member exists in template class parameter.

I'm basically trying to come up with a portable __if_exists macro found only in Microsoft land.


I have this in header file:


template<class Primitive, class Contact, class ContactManager, int MAX_LEVELS>
class A {
BOOST_MPL_HAS_XXX_TRAIT_DEF(getFirstContact);
[...]
void foo(Primitive* p);
void foo(Primitive* p, typename boost::enable_if<has_getFirstContact<Primitive> >::type *dummy=0);
}




in the cpp file:



template<class Primitive, class Contact, class ContactManager, int MAX_LEVELS>
void
A<Primitive, Contact, ContactManager, MAX_LEVELS>::foo(Primitive* p, typename boost::enable_if<has_getFirstContact<Primitive> >::type* dummy = 0)
{ ... }

template<class Primitive, class Contact, class ContactManager, int MAX_LEVELS>
void
A<Primitive, Contact, ContactManager, MAX_LEVELS>::foo(Primitive* p)
{ ... }




errors I'm getting in vc08:

[line in header file] error C2039: 'type' : is not a member of 'boost::enable_if<Cond>'

I'm probably missing a lot here...


Share this post


Link to post
Share on other sites
Advertisement
foo isn't templated, so it isn't subject to SFINAE, which is required to use enable_if. It belongs to a templated class, but that doesn't help. We can abuse specialization:

#include <boost/mpl/has_xxx.hpp>
#include <iostream>

template<class Primitive, class Contact, class ContactManager, int MAX_LEVELS>
class A {
BOOST_MPL_HAS_XXX_TRAIT_DEF(getFirstContact);

template < bool B > void foo_impl( Primitive* p ) { std::cout << "Has getFirstContact\n"; }
template <> void foo_impl<false>( Primitive* p ) { std::cout << "Does not have getFirstContact\n"; }
public:
void foo(Primitive* p) { foo_impl<has_getFirstContact<Primitive>::value>(p); }
};

struct No {};
struct Yes { typedef void getFirstContact; };

int main() {
A<No ,void,void,0> a; a.foo(0);
A<Yes,void,void,0> b; b.foo(0);
}

Share this post


Link to post
Share on other sites
okay... (BIG thanks for looking into this!) but here's what gcc tells me when I compile this:

GNU C++ version 4.2.1 (Apple Inc. build 5664) (i686-apple-darwin10)
compiled by GNU C version 4.2.1 (Apple Inc. build 5664).
GGC heuristics: --param ggc-min-expand=150 --param ggc-min-heapsize=131072
Compiler executable checksum: b2d9fc2676bcbc4fe5c6f07f902dbb00
/Users/ericlebel/pp.cpp:9: error: explicit specialization in non-namespace scope ‘class A<Primitive, Contact, ContactManager, MAX_LEVELS>’


so I guess it's no no with gcc... (specialization on function) ?

Share this post


Link to post
Share on other sites
Long story short, MaulingMonkey's example is actually non-standard C++ that Visual C++ doesn't mind, but GCC doesn't like, and as a general rule as far as I'm aware an explicit specialization of a templated member must be a member of an explicit specialization. Bit of a nasty problem (at least trying to figure it out this late it is), but try something like this:

BOOST_MPL_HAS_XXX_TRAIT_DEF(getFirstContact);

template<class Primitive, bool HasGetFirst>
class fooImpl
{
void foo(Primitive* p); // Version for when it's false
};

template<class Primitive>
class fooImpl<Primitive, true>
{
void foo(Primitive* p); // Version for when it's true
};

template<class Primitive, class Contact, class ContactManager, int MAX_LEVELS>
class A : public fooImpl<Primitive, has_getFirstContact<Primitive>::value> {
};




I'm sure there are better ways to work around the problem, but they'd probably depend on knowing more about the structure of your classes and what they're doing with each other.

EDIT: This is the kind of thing that good ol' fashioned polymorphism is best suited for dealing with.

Share this post


Link to post
Share on other sites
Other alternatives include making foo_impl a proper free function, explicitly passing in a pointer to the class and making it a friend of the class as necessary.

Share this post


Link to post
Share on other sites
thank you guys. I ended up using your suggestion Shinkage.


since I'm porting this code to the Mac, I have a lot of code to write in order to replace the __if_exists call...

(would it be thinkable to write a macro to replace __if_exists and make it portable ?)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!