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ただし、これは、上記の理由などのプリミティブ型の場合でも、常にtrueを報告します。これはC++の予想される/有効な動作ですか?

4

6 に答える 6

4

車輪を再発明しないでください。boost::is_class ブースト リファレンス マニュアルを使用する

あなたよりもよく知っている人たち。

于 2011-12-06T09:51:31.490 に答える
2

残念ながら、これは実際には不可能だと思います。

多くの問題が派生 (または少なくとも有用な派生) を妨げる可能性があり、そのfinal1 つが標準への追加です。

たとえば、Clang メーリング リストのこのスレッドfinalを参照してください。Howard Hinnant は、クラスがマークされているかどうかを確認するためにコンパイラ組み込み関数を必要としています。

于 2011-12-06T10:43:40.720 に答える
1

私は訪問者が持っていたように提案するつもりでした。ポインタを宣言してもテンプレートがインスタンス化されるとは思わないので、コンパイルされる可能性があります。ポインターを介してテンプレートを使用してメンバーにアクセスしてみてください。これにより、コンパイラーはテンプレートをインスタンス化するように強制されます。そうでなければ、私にはよくわかりませんが、整数型を継承できないことは知っています。

したがって、整数型を継承するテンプレートクラスをインスタンス化しようとすると、コードがコンパイルされない可能性があるため、答えは必要ないと思います。私は間違っているかもしれませんが、それがコンパイルされている唯一の理由は、ポインター型を作成してもテンプレートがインスタンス化されないためだと思います。

于 2011-12-06T09:57:30.037 に答える
1

SFINAE を介して派生可能なa を取得することは完全には不可能だと思います(これにはC++11 の場合も含まれます)。実行できる最善の方法は、型が a であるかどうかを検出するための SFINAE を用意し、それに依存することです。classfinal classclass

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
#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;

}

印刷します:

int
int
int *
int

予想通り..

誰かが他のライブラリから独立している必要があります...したがって、ライブラリをブーストすることは良い答えではありません。

于 2011-12-06T10:06:31.657 に答える
0

RTTI(Run Time Type Information) を使用して、クラスが属している型を知ることができます。また、クラスが基本型である場合、そのクラスが派生できないことがわかります。

例: if(typeid(T) == typeid(int) || typeid(T) == typeid(float)) { cout << "クラスを派生させることはできません"; }

必要に応じて、さらにタイプを IF 条件に追加できます

于 2011-12-06T09:49:25.500 に答える