4

すべての列挙型に対して operator<< を定義して、値を計算し、それが次のような列挙型であることを出力します。

コード:

enum AnyEnum{A,B,C};
AnyEnum enm = A;
cout << enm <<endl;

出力:

This is an enum which has a value equal to 0

is_enum構造体を使用して Boost ライブラリでこれを行う方法を知っています。しかし、私はそれがどのように機能するのか理解していません。そのため、一般的に、検証可能なものがクラス型、共用体型、または列挙型 (コンパイル時) であるかどうかを識別する方法に興味があります。

4

4 に答える 4

8

メンバーポインターが存在するという事実を使用できるクラスタイプを決定する

template<typename A, typename B>
struct issame { };

template<typename A>
struct issame<A, A> { typedef void type; };

template<typename> struct tovoid { typedef void type; };

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

template<typename C>
struct isclass<C, typename tovoid<int C::*>::type> {
  static bool const value = true;
};

ユニオン クラスと非ユニオン クラスの違いを検出することはできません。少なくとも私は方法を知りませんし、ブーストも知りません。

T列挙型の検出は、クラス、関数、または整数型ではないことを確認してから、整数型に割り当てようとすることで機能すると思います。あなたは出来る

template<typename E, typename = void> 
struct isenum { 
  struct No { char x; };
  struct Yes { No n1; No n2; };

  struct nullsink {};
  static No checkI(nullsink*); // accept null pointer constants
  static Yes checkI(...);

  static Yes checkE(int);
  static No checkE(...);

  static bool const value = (sizeof(checkI(E())) == sizeof(Yes)) && 
                            (sizeof(checkE(E())) == sizeof(Yes));
};

// class
template<typename E>
struct isenum<E, typename tovoid<int E::*>::type> {
  static bool const value = false;
};

// reference
template<typename R>
struct isenum<R&, void> {
  static bool const value = false;
};

// function (FuntionType() will error out).
template<typename F>
struct isenum<F, typename issame<void(F), void(F*)>::type> {
  static bool const value = false;
};

// array (ArrayType() will error out)
template<typename E>
struct isenum<E[], void> {
  static bool const value = false;
};
template<typename E, int N>
struct isenum<E[N], void> {
  static bool const value = false;
};

クイック & ダーティ テスト (GCC/clang/comeau で動作):

enum A { };
struct B { };
typedef int &C;
typedef void D();
typedef int E;
typedef long F;
typedef int const G;
typedef int H[1];

template<typename T, bool E>
struct confirm { typedef char x[(T::value == E) ? 1 : -1]; };

int main() {
  confirm< isenum<A>, true >();
  confirm< isenum<B>, false >();
  confirm< isenum<C>, false >();
  confirm< isenum<D>, false >();
  confirm< isenum<E>, false >();
  confirm< isenum<F>, false >();
  confirm< isenum<G>, false >();
  confirm< isenum<H>, false >();
}
于 2011-01-16T12:39:13.527 に答える
3

veriable がクラス型、ユニオン型、または列挙型 (コンパイル時) であるかどうかを識別する方法に興味があります。

boost::type_traits

C++ TR1でさえ<type_traits>、その機能をサポートするヘッダーを持っています。C++0x では、すべてが大幅に改善されます。

たとえば、次の機構はSFINAEを使用して、渡された引数がクラス型かどうかをチェックします。

template<typename T>struct Check_If_T_Is_Class_Type
{
    template<typename C> static char func (char C::*p);
    template<typename C> static long func (...);
    enum{val = CHECKER(func,Check_If_T_Is_Class_Type)};
};

マクロCHECKER

#define CHECKER(func_name,class_name) \
sizeof(class_name<T>::template func_name<T>(0)) == 1

type_traits がどのように機能するかを理解するには、テンプレートのメタプログラミングや SFINAE など、テンプレートに関する基本的な知識が必要です。

于 2011-01-16T12:32:52.983 に答える
0

これは通常、コンパイラ フックを使用して行われます。コンパイラには、適切な値でテンプレートを「埋める」特別な関数があります (少なくとも type_traits が標準化されている C++0x では)。たとえば、is_podトレイトは__is_podVC 10 でコンパイラ フックを使用して適切な情報を取得します。

于 2011-01-16T12:48:46.070 に答える
-3

コンパイル時に変数の型を知ることはできません。

于 2011-01-16T12:30:39.620 に答える