2017-10-16 3 views
4

boolというエラーステータスビットをstructの内部に格納する必要があります。今私は/ none /すべての変数が設定されているかどうかをチェックする方法が必要になります。C++はstruct内のすべてのステータスビットをチェックします

私はstd::bitsetがあることを知っていますが、インデックスではなく、名前でアクセスすることができます。だから私は、このような構造をした:

#include <cassert> 
union ErrorStatus 
{ 
    struct { 
     bool error1; 
     bool error2; 
     bool error3; 
    }; 
    std::array<bool, 3> bits; 
    bool any()const{ 
     return std::any_of(bits.begin(), bits.end(), [](const bool& b){return b == true; }); 
     } 
    bool none() const { 
     return !any(); 
    } 
    bool all()const{ 
     return !std::any_of(bits.begin(), bits.end(), [](const bool& b){return b == false; }); 
    } 

}; 

int main(int argc, char** argv) 
{ 

    ErrorStatus errorStatus; 
    assert(errorStatus.none() == true); 
    errorStatus.error2 = true; 
    assert(errorStatus.none() == false); 

    return 0; 
} 

しかし、これで、私はstruct内部ブール値の数と一致するようにstd::array宣言で番号を変更する必要があるという問題があります。

arrayのサイズとstructのboolの量を同期させる方法はありますか? もっとエレガントな(そしてうまくいけば良い)代替品がありますか?

+0

です。 STLの実装ではサイズに対して最適化が行われる可能性があります。その場合、使用できると思われる操作が利用できなくなります。 – Steve

+0

'std :: vector'を使うかもしれませんか? – Ron

+0

@Steveブールの数が動的でない場合、私はなぜあなたがベクトルを使用すべきかわかりません。固定サイズの配列に 'std :: array'を使う –

答えて

4

もっとエレガントな(そしてうまくいけば良い)代替品がありますか?

あなたは、配列の要素に名前を付けるenumを使用することができます。

enum { 
    error1, 
    error2, 
    error3, 
    errorsSize // must be last 
}; 

using ErrorStatus = std::array<bool, errorsSize>; 

ErrorStatus errors; 
errors[error1] = false; 

は「自動的に」配列のサイズを変更しますerrorsSize前に新しい列挙子を追加します。

+0

に感謝しました。今私はテンプレートとして列挙型を受け入れ、その値を 'COUNT'配列を割り当てるために使用する小さなラッパークラスを使用します。そして最初に 'enum'を定義し、最後に必要な値を追加するマクロがあります – Zaiborg

0

多分これは標準的なアルゴリズムであなたのエラー構造usabeを作る非常に読みやすいソリューションです:

#include <iostream> 
#include <algorithm> 

// Configure structure packing for Visual Studio. 
// See your compiler documentation on how to do this. 
#pragma pack(push) 
#pragma pack(1) 

struct Errors 
{ 
    bool error1; 
    bool error2; 
    bool error3; 

    inline const bool* begin() const 
    { 
     return reinterpret_cast<const bool*>(this); 
    } 

    inline const bool* end() const 
    { 
     return reinterpret_cast<const bool*>(this + 1); 
    } 

    inline bool any() const 
    { 
     return std::count(begin(), end(), true) > 0; 
    } 

    inline bool all() const 
    { 
     return std::count(begin(), end(), true) == end() - begin(); 
    } 

    inline bool none() const 
    { 
     return std::count(begin(), end(), true) == 0; 
    } 
}; 

#pragma pack(pop) 

私はしかし、これはコンパイラの実装固有のもので、私はいないだろう

int main() 
{ 

    Errors e; 
    memset(&e, 0, sizeof(e)); 

    e.error1 = false; 
    e.error2 = false; 
    e.error3 = false; 
    std::cout << "any=" << e.any() << ", all=" << e.all() << ", none=" << e.none() << std::endl; 

    e.error1 = true; 
    e.error2 = false; 
    e.error3 = false; 
    std::cout << "any=" << e.any() << ", all=" << e.all() << ", none=" << e.none() << std::endl; 

    e.error1 = true; 
    e.error2 = true; 
    e.error3 = true; 
    std::cout << "any=" << e.any() << ", all=" << e.all() << ", none=" << e.none() << std::endl; 

    return 0; 
} 

でテストこの方法で構造体を使用することをお勧めします。複数のエラー・コードを格納する

私のお気に入りの方法は、boolsのベクトルではなく、配列を使用し

enum class Enum 
{ 
    Error1, 
    Error2, 
    Error3 
}; 

typedef std::set<Error> Errors; 
+0

あなたが行っているポインタ演算は、そのオペランドが同じでないアレイ。さらに、これらの 'bool'メンバーは' struct'の中で連続しており、正確に 'sizeof(bool)'の間にあることが保証されていますか?私は確信していないが、そうは思わない。 –

+0

「同じ配列のメンバーではありません」とは何を意味するのかよく分かりません。 'this'は' Errors'型で、正確に1要素の 'Errors'の配列を指しています。したがって、「this + 1」は完全に合法です。あなたはパディングについて正しいです。標準ではカバーされていませんが、私が知っているすべてのコンパイラは、構造要素をそのサイズに合わせて整列します。したがって、構造全体に1つのタイプ(ここでは 'bool')しか使用されていない場合、パディングはまったく必要ありません。コンパイラに '#pragma(pack)'や '#pragma pack(1)'などのパディングを挿入するように指示することができます。 –

+0

Eh ...確かに、これはおそらく実際にはうまくいくでしょう。なぜなら、コンパイラはしばしば私たちの日を台無しにしてしまうからです。それは本当のコードの匂いのようだ! –

関連する問題