如何为模板函数指定可能的数据类型

How to specify possible data types for a template function

本文关键字:数据类型 函数      更新时间:2023-10-16

我正在尝试创建一个接受两种数据类型的函数,我知道每种数据类型都是drawable类的后代,这意味着我的函数依赖于drawable的一些函数。但是,因为它是一个模板函数,所以我不能这样做。

如何使用这些子类函数?还是让它只接受drawable的后代

这是我职能的开始。GetPositionY是可绘制的函数。

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

CheckCollision()函数应要求客户端传递一个提供GetPosition()方法的对象。这就是在模板中调用obj1->GetPositionX()时要做的操作。没有理由强迫它传递drawable对象。

通过组合使用:

boost::来自boost.TypeTraits的is_base_ofhttp://www.boost.org/doc/libs/1_46_1/libs/type_traits/doc/html/boost_typetraits/reference/is_base_of.html

和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
}

与C#不同,C#将假设最低的公分母,并需要使用"where"子句来解决此问题,C++采取的路径是在使用特定类型实际调用方法之前不检查模板类型的使用情况。因此,只有提供所需方法的类型才会编译。例如

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;
}

这里讨论了C#和C++泛型的这种差异。

drawable类添加一个特征结构,您可以使用它来测试模板中实例化的类型是否是正确的类型。这看起来像

//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; 
}

现在,如果过去的类型不可绘制,您的函数将简单地返回false,否则您可以继续测试,看看是否发生了冲突。