2011-06-27 23 views
2

我需要编写一个模板,它根据模板参数是否是某个类的实例来生成一些代码。可以为所有类生成模板,但只有在该类是其他类的代码应该执行的子类时才可以生成该模板。在没有类实例的情况下在C++模板中检查类

问题是,应该实现的函数没有收到类的任何实例,所以唯一已知的是类名。所以这是不可能的dynamic_cast实现这一目标,因为它要求的对象

template<T> 
class A 
{ 
    void somefunction(void) 
    { 
    if (T instanceof Foo) then ... 
    else ... 
    } 
} 

的情况下增加了一些解释

class X: public Foo {}; 
class Y {}; 

class A<X> {} // special logic is generated 
class A<Y> {} // special logic is NOT generated 
+0

如果你需要在模板实例美孚特殊行为,我Ť嗨,你不需要一个模板类,你需要一个模板方法模式... ...# –

+1

@Miguel天使:他只需要**它,如果他需要运行时多态性。 –

回答

3

您可以使用boost traits library 中的模板专业化或boost :: is_base_of,或者编写自己的特征,但不应该,因为您还没有掌握模板。

使用专业化,你可以

template<T> 
class A 
{ 
    void somefunction() { 
    // generic version 
    } 
}; 
template<> 
class A <Foo> 
{ 
    void somefunction() { 
    // foo version 
    } 
}; 

与往常一样,让我推荐Vandevoorde /约祖蒂斯 “C++模板:完全指南”。

如果担心代码膨胀,因为需要专业化只有一个memberfunction出许多,你仍然可以外包这个函数:

template <typename T> struct somefunction_helper { 
    static void thatfunction() { 
     // generic form 
    } 
}; 
template <> struct somefunction_helper<Foo> { 
    static void thatfunction() { 
     // Foo form 
    } 
}; 

template<T> 
class A 
{ 
    void somefunction() { 
    somefunction_helper<T>::thatfunction(); 
    } 
}; 
+0

is_base_of似乎很有前途 – Boris

1

无论是专业A或委托someFunction()成员函数模板的工作,一些免费的功能模板,你可以(完全)专注于T

+0

与上面相同的注释 - Foo仅为基类从未将其作为参数实例化的模板 – Boris

2

这是模板专门化的用途。他们更难写,但这就是你对他们所做的。例如:

template<T> class A 
{ 
    void somefunction(void) { 
     ...//default for any object type. 
    } 
}; 

template<> class A<Foo> 
{ 
    void somefunction(void) { 
     ...//specific to the type Foo. 
    } 
}; 

是的,它需要额外的工作。有一些模板元编程方法可以按照你想要的方式来完成,但其他人将不得不解释这些。

+0

Foo仅为基类从未将其作为参数实例化的模板 – Boris

+0

@Boris:您的评论没有任何意义。如果'A'永远不会被实例化,那么你的成员函数将永远不会被调用。 _If_实际上使用了'A',这里_will_是'T'的一个实际参数,并且这将起作用。 (请注意,Nicol和我的解决方案都不需要实例化类型为“T”的对象。) – sbi

+0

class X:Foo {},class Y {},A仅用X和Y作为参数实例化,而不是Foo本身(A 和A ) - 对于X类,应调用特殊逻辑。 – Boris

-1

编辑#2 - 请参阅工作示例。请注意,这是模板特化的运行时间(在编译时发生),并且需要启用RTTI。

#include <iostream> 
#include <typeinfo> 
using namespace std; 

class Foo {}; 
class X: public Foo {}; 
class Y {}; 

template<typename T> class A { 
public: 
    void somefunction() 
    { 
    if (typeid(T) == typeid(X)) { 
     cout << "X specific logic happening" << endl; 
    } 
    else { 
     cout << "Default behavior" << endl; 
    } 
    } 
}; 

int main() { 
    A<X> ax; 
    A<Y> ay; 
    ax.somefunction(); // prints "X specific logic happening" 
    ay.somefunction(); // prints "Default behavior" 
} 

typeid可以与模板被用来提取模板参数的类型 - 如下所述:

// expre_typeid_Operator_3.cpp 
// compile with: /c 
#include <typeinfo> 
template < typename T > 
T max(T arg1, T arg2) { 
    cout << typeid(T).name() << "s compared." << endl; 
    return (arg1 > arg2 ? arg1 : arg2); 
} 

来自http://msdn.microsoft.com/en-us/library/fyf39xec(v=vs.80).aspx

注意,值name()是实现定义的。

+0

name()的返回值是实现定义的,不应该依赖其内容。 –

+0

好吧 - 我正在更新答案,以包含'name()'的可移植性注意事项 – Nick

+0

这究竟是如何应用于解决手头的问题? – sbi

0

由于专业化将无法工作,因为模板参数将只导出从Foo,用什么另一个答案说:is_base_of,无论是从升压或标准库,如果它已经支持的部分地区的C++ 0x:

#include <type_traits> // C++0x 

class Foo{}; 

template<class T> 
class A{ 
    void specialOnFoo(){ 
    // dispatch the call 
    specialOnFoo(std::is_base_of<T, Foo>::type()); 
    } 

    void specialOnFoo(std::true_type){ 
    // handle Foo case 
    } 

    void specialOnFoo(std::false_type){ 
    // non-Foo case 
    } 
}; 
相关问题