C++ 检测类型是否可以从C++;

C++ 检测类型是否可以从C++;,c++,sfinae,template-meta-programming,C++,Sfinae,Template Meta Programming,我有以下模板类及其类型的(全局)变量: template <typename ClassT> struct ClassTester : public ClassT { typedef ClassT type; }; ClassTester<int> *aaa; // No error here 我想使用该类进行SFINAE测试,以确定给定类型是否是可以从以下内容派生的类: ClassTester<int> bbb; // Error here

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

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

ClassTester<int> *aaa;  // No error here
我想使用该类进行SFINAE测试,以确定给定类型是否是可以从以下内容派生的类:

ClassTester<int> bbb; // Error here
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测试(ClassTester*){}
模板
静态字符测试(…){}
静态常量布尔值=(sizeof(test(0))==sizeof(int));
};
但是,由于上述原因,即使对于
int
等基本类型,这也始终报告为真。这是一个预期的/有效的C++行为吗?

< p>您可以使用RTTI(运行时类型信息)来知道类属于什么类型,如果类是基本类型,则可以告诉该类不能从. 例: if(typeid(T)=typeid(int)| | typeid(T)==typeid(float)) {
不要重新发明轮子。使用boost::is_类


那些家伙比你更了解。

我打算像访问者一样建议。我不相信声明指针会实例化模板,这就是它可能会编译的原因。尝试通过指针访问使用模板的成员,这将迫使编译器实例化模板。否则,我不太确定-但我知道你无法继承整数类型

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

\35; include
#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我认为不可能完全获得一个通过SFINAE派生的
类(也包括C++11中的
最终类
),最好的办法是有一个SFINAE来发现一个类型是否是
,并依赖它

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;
};
模板
结构void{typedef void type;};
模板
结构可以从{
静态常量布尔值=假;
};
模板
结构可以从{
静态常量布尔值=真;
};

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

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

许多问题可能会妨碍推导(或至少是有用的推导),在标准中添加
final


例如,请参见Clang邮件列表中的Howard Hinnant要求编译器内部检查类是否标记为
final

谢谢您的回答,但我需要在编译时而不是运行时使用它。我怀疑原因是,简单地声明/定义指针并不需要实际实例化temp很晚了。毕竟,你没有使用
ClassTester*
做任何事情。类似的例子是检查模板参数是POD还是非POD。我打算像访问者那样建议。我不相信声明指针会实例化模板,这就是它可能编译的原因。尝试通过指针使用模板访问成员r、 这将迫使编译器实例化模板。否则,我不太确定-但我知道你不能继承整数类型。@Jeremy:然后它给出了一个类无法从int派生的编译器错误。这也很奇怪,我认为SFINAE只会拒绝重载而不抛出错误。boost::is_类做的有点不同东西-它测试给定的类型是否是类。我想测试类型是否可以从中派生。这两个在新的C++11标准中是不同的。我还没有发现任何Boost类型的特性可以帮助我实现这一点。我不认为他是有意粗鲁的。他说Boost已经为w所以你最好使用boost:is_类,或者至少看看它是如何实现的。我并不是故意粗鲁。你可以通过各种技术使一个类不可派生,例如,如果你没有在派生类中指定一个构造函数,那么在你尝试实例化一个派生类的变量之前,这个类肯定是无法检测到的(并等待编译器自动生成并发出错误).boost::is_类无疑是一种更简单、更可移植的方法来实现类似的目标。请参阅本帖中关于叮当声和final的评论。当我读到一些我想理解的东西时,被告知只使用其他人的解决方案,因为他们知道得更好,这是非常冒犯性的。我意识到这不是你的意图,但我非常清楚不喜欢这种形式的“答案”。如果我尝试访问指针,它会给出一个类无法从int派生的编译器错误。这也很奇怪,我认为SFINAE会拒绝重载,而不会抛出错误。尽管它不是100%的答案,但这绝对是一个有趣的方法。
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;
};