检测是否可以从C ++中派生类型

时间:2011-12-06 09:43:01

标签: c++ sfinae template-meta-programming

我有以下模板类和类型的(全局)变量:

template <typename ClassT>
struct ClassTester : public ClassT {
    typedef ClassT type;
};

ClassTester<int> *aaa;  // No error here

我希望编译错误,因为无法从int派生,但在Visual C ++ 2010下编译很好。

如果我删除了指针,我得到了预期的编译错误(int无法派生):

ClassTester<int> bbb; // Error here

我想用这个类进行SFINAE测试,看看给定的类型是否可以派生自:

template <typename T>
struct CanBeDerivedFrom  {

    template <typename C>
    static int test(ClassTester<T> *) { }

    template <typename>
    static char test(...) { }

    static const bool value = (sizeof(test<T>(0)) == sizeof(int));
};

然而,由于上述原因,即使对于int这样的原始类型,这也总是报告为真。这是C ++的预期/有效行为吗?

6 个答案:

答案 0 :(得分:4)

不要重新发明轮子。使用boost :: is_class boost reference manual

那些比你更了解的人。

答案 1 :(得分:2)

不幸的是,我认为这实际上是不可能的。

许多问题可能会阻止推导(或至少是有用的推导),final添加到标准为一。

例如,请参阅Clang邮件列表中的this thread,其中Howard Hinnant需要编译器内在函数来检查该类是否标记为final

答案 2 :(得分:1)

我打算像访客那样建议。我不相信声明一个指针会实例化模板,这就是为什么它可以编译。尝试通过指针使用模板访问成员,这将强制编译器实例化模板。否则,我不太确定 - 但我知道你不能继承整数类型。

所以,我认为答案是你不需要的,因为在你尝试实例化继承整数类型的模板类时,代码可能无法编译。我可能错了,但我相信它编译的唯一原因是因为创建指针类型不会实例化模板。

答案 3 :(得分:1)

我认为不可能完全获得可通过SFINAE派生的class(其中也包括C ++ 11中final class的情况)。最好的办法是让SFINAE找到一个类型是class并依赖它。

template<typename T>
struct void_ { typedef void type; };

template<typename T, typename = void>
struct CanBeDerivedFrom {
  static const bool value = false;
};

template<typename T>
struct CanBeDerivedFrom<T, typename void_<int T::*>::type> {
  static const bool value = true;
};

此元程序将查找给定类型是否为class/uniondemo

答案 4 :(得分:0)

您可以使用RTTI(运行时类型信息)来了解该类所属的类型,如果该类是基本类型,您可以告诉该类无法派生。

例:     if(typeid(T)== typeid(int)|| typeid(T)== typeid(float))     {         cout&lt;&lt; “这个班不能来自”;     }

您可以根据需要添加更多类型的IF条件

答案 5 :(得分:0)

#include <typeinfo>

main()
{
 int i;
 int * pi;
 cout << int is:  << typeid(int).name() << endl;
 cout <<   i is: << typeid(i).name() << endl;
 cout <<  pi is:  << typeid(pi).name() << endl;
 cout << *pi is:  << typeid(*pi).name() << endl << endl;

main() { int i; int * pi; cout << int is: << typeid(int).name() << endl; cout << i is: << typeid(i).name() << endl; cout << pi is: << typeid(pi).name() << endl; cout << *pi is: << typeid(*pi).name() << endl << endl;

打印:


int
int
int*
int

正如预期的那样..

某人需要独立于其他图书馆...所以提升图书馆并不是一个好的答案..