C から C++ に移植するプログラムで使用される一連のビット フラグがあります。
始める...
私のプログラムのフラグは、以前は次のように定義されていました。
/* Define feature flags for this DCD file */
#define DCD_IS_CHARMM 0x01
#define DCD_HAS_4DIMS 0x02
#define DCD_HAS_EXTRA_BLOCK 0x04
...これで、定数 (クラス定数などに対して) の #defines は一般的に悪い形式と見なされることがわかりました。
これにより、C++ でビット フラグを格納する最善の方法と、16 進数をこの方法で ("0x" を介して) 割り当てることができるように、C++ が int へのバイナリ テキストの割り当てをサポートしない理由について疑問が生じます。これらの質問は、この投稿の最後にまとめられています。
簡単な解決策の 1 つは、個々の定数を単純に作成することです。
namespace DCD {
const unsigned int IS_CHARMM = 1;
const unsigned int HAS_4DIMS = 2;
const unsigned int HAS_EXTRA_BLOCK = 4;
};
この考えを 1 としましょう。
私が持っていた別のアイデアは、整数列挙型を使用することでした:
namespace DCD {
enum e_Feature_Flags {
IS_CHARMM = 1,
HAS_4DIMS = 2,
HAS_EXTRA_BLOCK = 8
};
};
しかし、これについて私を悩ませていることの1つは、より高い値になると直感的でなくなることです.
namespace DCD {
enum e_Feature_Flags {
IS_CHARMM = 1,
HAS_4DIMS = 2,
HAS_EXTRA_BLOCK = 8,
NEW_FLAG = 16,
NEW_FLAG_2 = 32,
NEW_FLAG_3 = 64,
NEW_FLAG_4 = 128
};
};
このアプローチをオプション 2 と呼びましょう。
Tom Torf のマクロ ソリューションの使用を検討しています。
#define B8(x) ((int) B8_(0x##x))
#define B8_(x) \
( ((x) & 0xF0000000) >( 28 - 7 ) \
| ((x) & 0x0F000000) >( 24 - 6 ) \
| ((x) & 0x00F00000) >( 20 - 5 ) \
| ((x) & 0x000F0000) >( 16 - 4 ) \
| ((x) & 0x0000F000) >( 12 - 3 ) \
| ((x) & 0x00000F00) >( 8 - 2 ) \
| ((x) & 0x000000F0) >( 4 - 1 ) \
| ((x) & 0x0000000F) >( 0 - 0 ) )
インライン関数に変換されます。
#include <iostream>
#include <string>
....
/* TAKEN FROM THE C++ LITE FAQ [39.2]... */
class BadConversion : public std::runtime_error {
public:
BadConversion(std::string const& s)
: std::runtime_error(s)
{ }
};
inline double convertToUI(std::string const& s)
{
std::istringstream i(s);
unsigned int x;
if (!(i >> x))
throw BadConversion("convertToUI(\"" + s + "\")");
return x;
}
/** END CODE **/
inline unsigned int B8(std::string x) {
unsigned int my_val = convertToUI(x.insert(0,"0x").c_str());
return ((my_val) & 0xF0000000) >( 28 - 7 ) |
((my_val) & 0x0F000000) >( 24 - 6 ) |
((my_val) & 0x00F00000) >( 20 - 5 ) |
((my_val) & 0x000F0000) >( 16 - 4 ) |
((my_val) & 0x0000F000) >( 12 - 3 ) |
((my_val) & 0x00000F00) >( 8 - 2 ) |
((my_val) & 0x000000F0) >( 4 - 1 ) |
((my_val) & 0x0000000F) >( 0 - 0 );
}
namespace DCD {
enum e_Feature_Flags {
IS_CHARMM = B8("00000001"),
HAS_4DIMS = B8("00000010"),
HAS_EXTRA_BLOCK = B8("00000100"),
NEW_FLAG = B8("00001000"),
NEW_FLAG_2 = B8("00010000"),
NEW_FLAG_3 = B8("00100000"),
NEW_FLAG_4 = B8("01000000")
};
};
これはクレイジーですか?それとも、より直感的に見えますか?この選択を 3 としましょう。
要約すると、私の包括的な質問は次のとおりです。
1. なぜ c++ は "0x" のような "0b" 値フラグをサポートしないのですか?
2. フラグを定義するのに最適なスタイルはどれですか...
i. 名前空間でラップされた定数。
ii. 直接割り当てられた unsigned int の名前空間でラップされた列挙型。
iii. 読み取り可能なバイナリ文字列を使用して割り当てられた unsigned int の名前空間でラップされた列挙型。
前もって感謝します!また、このスレッドを主観的なものとして閉じないでください。最適なスタイルとは何か、および c++ にバイナリ代入機能が組み込まれていない理由について本当に助けてもらいたいからです。
編集1
少し追加情報。ファイルから 32 ビットのビットフィールドを読み取り、これらのフラグを使用してテストします。したがって、提案を投稿するときは、そのことを念頭に置いてください。