C++ 特定基类的C++类模板
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2012950/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++ class template of specific baseclass
提问by Mat
Let's say I have the classes:
假设我有这些课程:
class Base{};
class A: public Base{
int i;
};
class B:public Base{
bool b;
};
And now I want to define a templated class:
现在我想定义一个模板化类:
template < typename T1, typename T2 >
class BasePair{
T1 first;
T2 second;
};
But I want to define it such that only decendants of class Base can be used as templateparameters.
但我想定义它,以便只有 Base 类的后代可以用作模板参数。
How can I do that?
我怎样才能做到这一点?
采纳答案by user213546
More exactly:
更准确地说:
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
}
回答by Hashbrown
C++11 introduces <type_traits>
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;
};
回答by Konrad Rudolph
C++ doesn't yet allow this directly. You can realize it indirectly by using a STATIC_ASSERT
and type checkinginside the class:
C++ 还不允许直接这样做。您可以通过在类中使用 aSTATIC_ASSERT
和类型检查来间接实现它:
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;
};
回答by RC.
This was a great question! While researching this via this link, I came up with the following, which admittedly isn't much different than the provided solution there. Learn something everyday...check!
这是一个很好的问题!在通过此链接进行研究时,我想出了以下内容,无可否认,这与那里提供的解决方案没有太大区别。每天学习一些东西......检查!
#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;
}
回答by mukeshkumar
In the answer suggested by unknown(yahoo), it is not required to actually have the variables of type X and Y as members. These lines are sufficient in the constructor:
在 unknown(yahoo) 建议的答案中,实际上不需要将 X 和 Y 类型的变量作为成员。这些行在构造函数中就足够了:
static_cast<B*>((X*)0);
static_cast<B*>((Y*)0);
回答by alemjerus
First, fix the declaration
首先,修复声明
template < class T1, class T2 >
class BasePair{
T1 first;
T2 second;
};
Then, you can declare in a base class some private function Foo(); and tell Base class to have BasePair as friend; then in friend constructor you just have to call this function. This way you will get compile-time error when someone tries to use other classes as template parameters.
然后,您可以在基类中声明一些私有函数 Foo(); 并告诉 Base 类以 BasePair 为好友;然后在朋友构造函数中你只需要调用这个函数。这样,当有人尝试使用其他类作为模板参数时,您将收到编译时错误。
回答by user213546
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);
}
};