6

コンパイル時に、指定された値が指定された列挙型の値内にあることを確認する方法はありますか?したがって、有効ですか?

enum myenum { val1 = 10, val2 = 30, val3 = 45 }

template <myenum t>
class myClass
{ ... }

myClass<10> a; // fails, OK
myClass<val1> b; // compiles OK
myClass<myenum(24)> c; //compiles, NOT OK!

2 番目のテンプレートの非型ブール値パラメーターを使用すると、その値が myenum の値の範囲内にあることを検証するメタ関数によってそのブール値が与えられます。

列挙型を反復する方法など、さまざまな列挙型関連の質問に目を通しましたが、それはできないようです。

4

5 に答える 5

5
enum myenum { val1 = 10, val2 = 30, val3 = 45 };
template<myenum e> struct is_valid_myenum { static const bool value = (e==val1 || e==val2 || e==val3); };

template<myenum t>
class myClass
{
    static_assert(is_valid_myenum<t>::value, "t must be a valid enum value");
};

myClass<10> a; // fails, OK
myClass<val1> b; // compiles OK
myClass<myenum(24)> c; // fails, OK

本当に重複を避けたい場合(そしてソースコードを生成するために外部ツールを使用することに興味がない場合)は、マクロハッカーに頼ることができます。

#define LIST \
    ITEM(val1,10)\
    ITEM(val2,30)\
    ITEM(val3,45)

#define ITEM(NAME,VALUE) NAME = VALUE,

enum myenum { LIST };

#undef ITEM

#define ITEM(NAME,VALUE) e==NAME ||

template<myenum e> struct is_valid_myenum { static const bool value = ( LIST false ); };

template<myenum t>
class myClass
{
    static_assert(is_valid_myenum<t>::value, "t must be a valid enum value");
};

myClass<10> a; // fails, OK
myClass<val1> b; // compiles OK
myClass<myenum(24)> c; // fails, OK
于 2012-06-22T19:08:33.627 に答える
2

他の開発者が自分の足で撃つことを決して防ぐことはできません. あなたは決して勝つことはできません。API がそれを簡単にしないようにしてください。

彼が無効な値を取得してキャストし、それをあなたに渡した場合、それは純粋に彼の問題です。これは、型のポインターをパラメーターとして取る関数を彼に提供した場合と同じ種類の問題ですが、彼T*は (任意の型の) ランダムなデータを取り、それをキャストしてT*渡します。

これがキャストの仕組みです。キャストを行う人は、キャストされた式がキャスト先の型の値として安全に解釈できることを保証する責任があります。

于 2012-06-22T19:07:07.537 に答える
0

値が実行時に列挙型の有効な範囲内にあることを確認する方法はありません。コンパイル時に確認する方法はありません。

チェックする唯一の方法は、すべての値を力ずくでチェックすることです。このようなもの:

enum lala
{
  A = 10,
  B = 20,
  C = 30
};

template< int value >
struct T
{
  static_assert( (value == A) || (value == B ) || (value == C), "wrong value" );
};

int main()
{
  T< 10 > t10;
  T< 20 > t20;
  T< 25 > t25;
  T< 30 > t30;

  (void)t10;(void)t20;(void)t25;(void)t30;
}
于 2012-06-22T19:09:35.233 に答える
0

すべての情報をメタプログラミング形式で再宣言しない限り、それはできません。ただし、たとえば次のことができます。

enum myenum { val1 = 10, val2 = 30, val3 = 45 };
typedef vector_c< myenum, val1, val2, val3 > typed_myenum;

typedef
    contains< typed_myenum, integral_c< myenum, val >::value
    val_found;

Boost.MPLの機能を使用しますが、実際の構文は少しずれている可能性があります。

于 2012-06-22T19:06:54.277 に答える
0

列挙型の名前が重要でない場合は、次のように配列に転送できます。

const int myenum[]={10,30,45}

次に、インデックスを使用してミエナムからそれらを参照します。

template<unsigned int t>
class myClass
{
    static_assert(t < sizeof(myenum)/sizeof(int), "t must be a valid enum index");
    int val=myenum[t];
    ...
};
于 2012-06-22T21:21:03.087 に答える