2

このマクロを考えると

#define MAKE_TYPE(_a, _b, _c, _d) ((_a) | ((_b) << 8) | ((_c) << 16) | ((_d) << 24))

代わりに配列[4]を取るように置き換えたいと思います。醜い MAKE_TYPE('A', 'B', 'C', 'D') の代わりに MAKE_TYPE("ABCD") を書くことができるように

コンパイル時にこれを使用して、いくつかの定数を生成しています。

しかし、このような文字列を渡すのは好きではありません

#define MAKE_TYPE(s) ((s[3]) | ((s[2]) << 8) | ((s[1]) << 16) | ((s[0]) << 24))

エラー: 定数式に配列参照を指定することはできません

それはうまくいきませんでした。だから私はテンプレートメタプログラミングを使ってそれを試してみようと思った.

template< char[4] s > class MAKE_TYPE
{
 public:
 enum{ RESULT = s[3] | (s[2] << 8) | (s[1] << 16) | (s[0] << 24) };
};

残念ながら、これもうまくいきませんでした。テンプレートに char[4] を入れることができないようです。そして、私はこれらのエラーを受け取ります:

エラー: 's' の前に '>' が必要です エラー: 's' はこのスコープで宣言されていません エラー: 配列参照は定数式に表示できません

どうすればいいですか?

4

5 に答える 5

2

もう少し括弧やキャストを試しましたか?

#define MAKE_TYPE(s) (int((s)[3]) | (int((s)[2]) << 8) | (int((s)[1]) << 16) | (int((s)[0]) << 24))

これは私にとってはうまくいきます。私はFourCCコードに非常によく似たものを使用し、私のマクロは多くの異なるコンパイラーによって使用されています。

于 2011-04-07T10:48:14.317 に答える
2

エラー メッセージは、「配列は定数式に使用できません」という意味です。

テンプレート式は定数式でなければならないため、配列をテンプレート引数に含めることはできません。

配列へのポインタを持つこともできますが、それはあなたが望むものではありません。

ああ、制限はわずか 4 文字なので'ABCD'、一重引用符などで複数文字の定数を使用できます。ただし、文字の順序は実装定義です。

あなたが試みているように見えるもう1つのことは、文字定数からクラス自体の名前を生成することです。これは、文字リテラルではなく生の文字をマクロに渡す場合に可能ですが、実際にはそうではありません。たとえそれがうまくいったとしても、それはかなり地獄でしょう。

于 2011-04-07T10:37:39.160 に答える
0

このようなものはどうですか?

template <typename T>
typename boost::enable_if_c<(T('1234')==0x31323334), T>::type
make(T v)
{
    return v;
}

const int value = make('ABCD');

これは、複数文字定数のコンパイラ依存の動作に対するセーフティ ネットです。必要に応じてバイトを切り替えて、さまざまなコンパイラの動作にさらに実装を追加できます。'1234'これは、評価のバイト順がコンパイラごとに一貫していることを前提としています。

テンプレートの専門家が改良できる場合があります。

于 2011-04-07T13:02:56.030 に答える
0

入力が次のとおりであることがわかっている場合char *:

template <class RT> RT MakeType( const char * _arg )
{
  return _arg[3] | (_arg[2] << 8) | (_arg[1] << 16) | (_arg[0] << 24);
}

そうしないと:

template <class T, class RT> RT MakeType( const T &B0, const T &B1, const T &B2, const T &B3 )
{
  return B3 | (B2 << 8) | (B1 << 16) | (B0 << 24);
}

私はするだろう:

inline unsigned int MakeType( const char * _arg )
{
  return _arg[3] | (_arg[2] << 8) | (_arg[1] << 16) | (_arg[0] << 24);
}

必要に応じてキャストします。

于 2011-04-07T10:36:50.880 に答える
0

複数文字の定数を使用できますint four = 'four'。ただし、動作はコンパイラ固有です。

于 2011-04-07T10:42:08.797 に答える