开发者

How to specify possible data types for a template function

I'm trying to make a function that takes two data types, each of which I know will be a descendent of a drawable class, meaning my function depends on some of drawable's functions. However because it is a template function I can't do this.

How can I make it so I can use these descendant class functions? Or make it so only descendents of drawable are accepted?

here's the beginning of my function. GetPositionY is drawable's function.

template<typename T, typename T2>
bool CheckCollision(T* o开发者_C百科bj1, T2* obj2){
    obj1->GetPositionY;


A CheckCollision() function shall require the client to pass an object that provides GetPosition() methods. That's what you do when calling obj1->GetPositionX() inside your template. There's no reason to force it to pass a drawable object.


By using a combination of :

boost::is_base_of from Boost.TypeTraits http://www.boost.org/doc/libs/1_46_1/libs/type_traits/doc/html/boost_typetraits/reference/is_base_of.html

and boost::enable_if

http://www.boost.org/doc/libs/1_46_1/libs/utility/enable_if.html

template<typename T, typename T2>
typename boost::enable_if< boost::is_base_of< Drawable, T1>, bool>::type 
CheckCollision(T* obj1, T2* obj2)
{
  obj1->GetPositionY(); // ... whatever
}


Unlike C#, which will assume the lowest common denominator and requires the use of the "where" clause to resolve this, C++ takes the path of not checking the template type usage until the method is actually invoked with a specific type. So only types that provide the required methods will compile. e.g.

template<typename T, typename T2>
bool CheckCollision(T* obj1, T2* obj2) {
        obj1->GetPositionY;
}

class A
{
        public:
                int GetPositionY;
                A() { };
};

class B
{
        public:
                B() { };
};

int main(int argc, char* argv[])
{
        A a;
        B b;

        // this compiles just fine
        CheckCollision(&a, &a);
        // this line will not compile, "error: 'class B' has no member named 'GetPositionY'"
        // CheckCollision(&b, &b);

        return 0;
}

There is a discussion about this difference with C# and C++ generics here.


Add a trait structure for your drawable class that you can use to test whether the types instantiated in the template are the correct types. This would look something like

//default for any data-type
template<typename T>
struct drawable_type
{
    enum { drawable = 0 };
};

//specialization for a drawable class
template<>
struct drawable_type<drawable>
{
    enum { drawable = 1 };
};

template<typename T, typename T2>
bool CheckCollision(T* obj1, T2* obj2) 
{ 
    if (drawable_type<T>::drawable && drawable_type<T2>::drawable)
    {
        //do something
    }
    else
        return false; 
}

Now if the types past aren't drawable, your function will simply return false, otherwise you can continue to test and see if a collision occurred.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜