現在、構造体に基づいて整数ベースの状態を生成するかなりの解決策を考え出しています。structメンバ関数の値に基づいて状態を生成します。
この関数は、構造体のインスタンスを取得し、メンバ変数に基づいて一意の状態を生成する必要があります。
手作業でチェックしたり、すべての可能性を設定して状態を生成したりしない、きわめて簡単な解決策は何ですか?
現在、構造体に基づいて整数ベースの状態を生成するかなりの解決策を考え出しています。structメンバ関数の値に基づいて状態を生成します。
この関数は、構造体のインスタンスを取得し、メンバ変数に基づいて一意の状態を生成する必要があります。
手作業でチェックしたり、すべての可能性を設定して状態を生成したりしない、きわめて簡単な解決策は何ですか?
ビットセット(std::bitset
または符号なし数値タイプ)を使用して、独自の状態を表すことができます。
あなたが必要になります。
busy
ため。powered
の場合は1ビットです。direction
の場合は1ビットです。speed
の2ビット。合計で、可能なすべての組み合わせを表すには5ビットが必要です。
例:
auto status::hash() const noexcept
{
std::bitset<5> b;
b |= speed; // assumes only the last two bits in `speed` are used
b.set(4, busy);
b.set(3, powered);
b.set(2, direction);
return b;
}
'std :: bitset'を' int8'に変換すると、不一致が発生しますか? –
@CarltonBanks:不一致はありません。変換の例については、[この質問](http://stackoverflow.com/questions/19583720/convert-bitset-to-int-in-c)を参照してください。あるいは、同じロジックを使用して、 'std :: uint8_t'で直接ビット演算を行うことができます。 –
としてstd::bitset
として良いが、あなたはビットフィールドを使用して、単一のバイトでstruct全体を格納することができない:
struct status {
public:
status(Busy busy, Speed speed, Powered powered, Direction direction)
: busy{busy}, speed{speed}, powered{powered}, direction{direction}, pad{0} {};
Busy busy : 1;
Speed speed : 2;
Powered powered : 1;
Direction direction : 1;
unsigned char pad : 3; // pad to 8 bits
};
完全なプログラム:
#include <bitset>
#include <iostream>
#define ENUM_MACRO3(name, v1, v2, v3)\
enum class name : unsigned char { v1, v2, v3};\
std::ostream& operator<<(std::ostream& os, name var) {\
switch (var){\
case name::v1: return os << #v1;\
case name::v2: return os << #v2;\
case name::v3: return os << #v3;\
}\
return os;\
}
#define ENUM_MACRO2(name, v1, v2)\
enum class name : unsigned char { v1, v2};\
std::ostream& operator<<(std::ostream& os, name var) {\
switch (var){\
case name::v1: return os << #v1;\
case name::v2: return os << #v2;\
}\
return os;\
}
ENUM_MACRO3(Speed, fast, medium, slow)
ENUM_MACRO2(Busy, handling, not_handling)
ENUM_MACRO2(Powered, on, off)
ENUM_MACRO2(Direction, forwards, backwards)
struct status {
public:
status(Busy busy, Speed speed, Powered powered, Direction direction)
: busy{busy}, speed{speed}, powered{powered}, direction{direction}, pad{0} {};
Busy busy : 1;
Speed speed : 2;
Powered powered : 1;
Direction direction : 1;
unsigned char pad : 3; // pad to 8 bits
};
int main()
{
status s{Busy::not_handling,Speed::slow,Powered::off,Direction::backwards};
std::cout << "Data has size of " << sizeof(status) << '\n';
std::cout << "busy :" << s.busy << '\n';
std::cout << "speed :" << s.speed << '\n';
std::cout << "powered :" << s.powered << '\n';
std::cout << "direction :" << s.direction << '\n';
unsigned char val = reinterpret_cast<unsigned char&>(s);
unsigned int num{val};
std::cout << num << '\n';
std::bitset<8> bs{num};
std::cout << bs << '\n';
return 0;
}
生成します:
Data has size of 1
busy :not_handling
speed :slow
powered :off
direction :backwards
29
00011101
心に留めておくべきいくつかのポイント:
std::bitset
でハッシュを生成するのが最善でしょう。
だから、この 'struct'を'ハッシュ 'したいですか? – NathanOliver
hmmm ...おもしろい...うーん、ハッシュ関数..生成されたキーが整数の場合。 –
あなたの質問に対する答えではなく、単なる提案です。 'true'と' false'が説明を必要とし、スピード値の数が限られているだけでは、enumを使うことができます。 'FORWARD'や' BACKWARDS'のような名前はコードで読みやすく、人々はどの値を参照する必要はありません。 – Hayt