6

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

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++ 的预期/有效行为吗?

4

6 回答 6

4

不要重新发明轮子。使用 boost::is_class 升压参考手册

那些比你更了解的人。

于 2011-12-06T09:51:31.490 回答
2

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

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

例如,请参阅Clang 邮件列表中的此线程,其中 Howard Hinnant 需要编译器内部来检查该类是否被标记为final

于 2011-12-06T10:43:40.720 回答
1

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

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

于 2011-12-06T09:57:30.037 回答
1

我认为不可能完全获得class可通过 SFINAE 派生的 a(其中也包括final classC++11 中的情况)。可以做的最好的事情是拥有一个 SFINAE 来查找类型是否为 aclass并依赖它。

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/union存在。演示

于 2011-12-06T10:25:13.510 回答
0

您可以使用 RTTI(运行时类型信息)来了解该类属于哪种类型,如果该类是基本类型,则可以判断该类不能派生自该类。

例如: if(typeid(T) == typeid(int) || typeid(T) == typeid(float)) { cout << "类不能派生"; }

如果需要,您可以向 IF 条件添加更多类型

于 2011-12-06T09:49:25.500 回答
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;

}

它打印:

整数
整数
整数*
整数

正如预期的那样。。

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

于 2011-12-06T10:06:31.657 回答