特定基类的C ++类模板
比方说,我有类:
class Base{}; class A: public Base{ int i; }; class B:public Base{ bool b; };
现在我想定义一个模板类:
template < typename T1, typename T2 > class BasePair{ T1 first; T2 second; };
但是我想定义它,只有类Base的后代可以用作模板参数。
我怎样才能做到这一点?
更确切地说:
class B {}; class D1 : public B {}; class D2 : public B {}; class U {}; template <class X, class Y> class P { X x; Y y; public: P() { (void)static_cast<B*>((X*)0); (void)static_cast<B*>((Y*)0); } }; int main() { P<D1, D2> ok; P<U, U> nok; //error }
C ++ 11引入了<type_traits>
template <typename T1, typename T2> class BasePair{ static_assert(std::is_base_of<Base, T1>::value, "T1 must derive from Base"); static_assert(std::is_base_of<Base, T2>::value, "T2 must derive from Base"); T1 first; T2 second; };
C ++不直接允许这个。 您可以通过使用STATIC_ASSERT
间接实现它,并在类内部进行types检查 :
template < typename T1, typename T2 > class BasePair{ BOOST_STATIC_ASSERT(boost::is_base_of<Base, T1>); BOOST_STATIC_ASSERT(boost::is_base_of<Base, T2>); T1 first; T2 second; };
这是一个很好的问题! 在通过这个链接研究这个问题的时候,我提出了以下内容,这与所提供的解决scheme没有多大区别。 每天学点东西…检查!
#include <iostream> #include <string> #include <boost/static_assert.hpp> using namespace std; template<typename D, typename B> class IsDerivedFrom { class No { }; class Yes { No no[3]; }; static Yes Test(B*); // declared, but not defined static No Test(...); // declared, but not defined public: enum { IsDerived = sizeof(Test(static_cast<D*>(0))) == sizeof(Yes) }; }; class Base { public: virtual ~Base() {}; }; class A : public Base { int i; }; class B : public Base { bool b; }; class C { string z; }; template <class T1, class T2> class BasePair { public: BasePair(T1 first, T2 second) :m_first(first), m_second(second) { typedef IsDerivedFrom<T1, Base> testFirst; typedef IsDerivedFrom<T2, Base> testSecond; // Compile time check do... BOOST_STATIC_ASSERT(testFirst::IsDerived == true); BOOST_STATIC_ASSERT(testSecond::IsDerived == true); // For runtime check do.. if (!testFirst::IsDerived) cout << "\tFirst is NOT Derived!\n"; if (!testSecond::IsDerived) cout << "\tSecond is NOT derived!\n"; } private: T1 m_first; T2 m_second; }; int main(int argc, char *argv[]) { A a; B b; C c; cout << "Creating GOOD pair\n"; BasePair<A, B> good(a, b); cout << "Creating BAD pair\n"; BasePair<C, B> bad(c, b); return 1; }
class B { }; class D : public B { }; class U { }; template <class X, class Y> class P { X x; Y y; public: P() { (void)static_cast<X*>((Y*)0); } };
首先,确定声明
template < class T1, class T2 > class BasePair{ T1 first; T2 second; };
然后,你可以在一个基类中声明一些私有函数Foo(); 并告诉Base类有BasePair作为朋友; 那么在朋友的构造函数中,你只需要调用这个函数。 这样,当有人试图使用其他类作为模板参数时,你将得到编译时错误。
在由unknown(yahoo)build议的答案中,不需要实际上具有typesX和Y的variables作为成员。 这些行在构造函数中是足够的:
static_cast<B*>((X*)0); static_cast<B*>((Y*)0);