web-dev-qa-db-ja.com

vector <bool>の代替

(願わくば)ご存知のように、_vector<bool>_は完全に壊れており、C配列として扱うことはできません。この機能を取得する最良の方法は何ですか?これまでのところ、私が考えたアイデアは次のとおりです。

  • 代わりに_vector<char>_を使用するか、または
  • ラッパークラスを使用し、_vector<bool_wrapper>_

この問題にどう対処しますか? c_array()機能が必要です。

副質問として、c_array()メソッドが必要ない場合、ランダムアクセスが必要な場合にこの問題に対処する最善の方法は何ですか? dequeまたは他の何かを使用する必要がありますか?

編集:

  • 動的なサイジングが必要です。
  • 知らない人のために、_vector<bool>_は、各boolが1ビットを取るように特化されています。したがって、Cスタイルの配列に変換することはできません。
  • 「ラッパー」は少し間違った名前だと思います。私はこのようなことを考えていました:

もちろん、アライメントの問題の可能性があるため、_my_bool_を読み込む必要があります:(

_struct my_bool
{
    bool the_bool;
};
vector<my_bool> haha_i_tricked_you;
_
86
rlbond

使用する - std::deque 配列が必要ない場合は、はい。

それ以外の場合は、 Boost Container のようなvectorに特化しない代替boolを使用します。

38

それは興味深い問題です。

特殊化されていない場合にstd :: vectorであったものが必要な場合、そのような何かがあなたのケースでうまくいくかもしれません:

#include <vector>
#include <iostream> 
#include <algorithm>

class Bool
{
public:

    Bool(): m_value(){}
    Bool( bool value ) : m_value(value){}

    operator bool() const { return m_value;}

    // the following operators are to allow bool* b = &v[0]; (v is a vector here).
    bool* operator& () { return &m_value; }
const bool * const operator& () const { return &m_value; }

private:

    bool m_value;

};




int main()
{
    std::vector<Bool> working_solution(10, false);


    working_solution[5] = true;
    working_solution[7] = true;


    for( int i = 0; i < working_solution.size(); ++i )
    {
        std::cout<< "Id " << i << " = " << working_solution[i] << "(" <<(working_solution[i] ? "true" : "false") << ")" <<std::endl; // i used ? : to be sure the boolean evaluation is correct
    }

    std::sort( working_solution.begin(), working_solution.end());
    std::cout<< "--- SORTED! ---" << std::endl;

    for( int i = 0; i < working_solution.size(); ++i )
    {
            bool* b = &working_solution[i]; // this works!

        std::cout<< "Id " << i << " = " << working_solution[i] << "(" << (working_solution[i] ? "true" : "false") << ")" <<std::endl; // i used ? : to be sure the boolean evaluation is correct
    }

    std::cin.get();
    return 0;
}

VC9でこれを試しましたが、うまくいくようです。 Boolクラスの考え方は、同じ動作とサイズ(ただし同じタイプではない)を提供することにより、boolタイプをシミュレートすることです。ほとんどすべての作業は、bool演算子とデフォルトのコピーコンストラクターによって行われます。アルゴリズムを使用するときに想定どおりに反応するようにソートを追加しました。

すべてのケースに適しているかどうかはわかりません。あなたのニーズに合っていれば、ベクターのようなクラスを書き換えるよりも作業が少なくなります...

20
Klaim

ニーズに依存します。私はどちらかに行きますstd::vector<unsigned char>。ラッパーの作成は、機能のサブセットのみを使用する場合は問題ありませんが、そうでない場合は悪夢になります。

この問題にどう対処しますか? c_array()機能が必要です。

boost::container::vector<bool>

vector<bool>特殊化は非常に問題が多く、非推奨または標準から削除する試みがいくつか失敗しました。 Boost.Containerは、優れたBoost.DynamicBitsetソリューションがあるため、実装しません。

...

boost :: container :: vector :: iteratorは実際のブール参照を返し、完全に準拠したコンテナとして機能します。 boost :: container :: vector<bool>機能のメモリ最適化バージョンが必要な場合は、Boost.DynamicBitset

12
Evgeny Panasyuk

Vector <int>の使用を検討してください。一度コンパイルと型チェックを終えると、boolとintはどちらも単なる機械語になります(編集:これは常に正しいとは限りませんが、多くのPCアーキテクチャで当てはまります)。警告なしで変換する場合は、「bool foo = !! bar」を使用します。これは、ゼロをfalseに、非ゼロをtrueに変換します。

Vector <char>などはスペースを使用しませんが、文字はマシンのWordサイズよりも小さいため、状況によっては(非常に小さな)速度に達する可能性もあります。これが、boolがcharの代わりにintを使用して実装される主な理由だと思います。

明確なセマンティクスが本当に必要な場合は、独自のブール型クラスを作成することもお勧めします。

また、C++標準から削除されたvector <bool>特殊化を希望する人々のクラブへようこそ(それを置き換えるbit_vectorを使用)。それはすべてのクールな子供たちがたむろする場所です:)。

5
AHelps

最も簡単な答えは、sbが_vector<struct sb>_である_struct {boolean b};_を使用することです。次に、Push_back({true})と言うことができます。良いように思える。

4
Todd

この問題はすでに discussed comp.lang.c ++。moderatedで発生していました。提案されたソリューション:

  • 独自のアロケータ(std::allocatorに基づく)および独自のベクトル特殊化。
  • std::dequeを使用します(S. Mayersの書籍のいずれかで既に推奨されていました)-ただし、これは要件に合っていません。
  • pOD boolラッパーを作成します。
  • 代わりにcharと同じサイズの何か(int/bool/etc)を使用してくださいbool;

また、標準委員会の提案を見ました-マクロ(STD_VECTOR_BOOL_SPECIALのようなもの)を導入してこの専門化を禁止します-しかし、この提案はstl実装では実装されず、承認されませんでした。

あなたの問題にはこれをうまくやる方法がないようです...たぶんC++ 0xで。

4
bayda

私が推奨する回避策は、vectorの基本型を持つスコープ付き列挙型のboolです。これは、委員会がそれを専門化していなかった場合に得ていたvector<bool>にかなり近づきます。

enum class switch_status : bool { ON, OFF };

static_assert( sizeof( switch_status ) == 1 );

::std::vector<switch_status> switches( 20, switch_status::ON );

static_assert( ::std::is_same_v< decltype( switches.front() ), switch_status &> );
static_assert( ::std::is_same_v< decltype( switches.back()  ), switch_status &> );
static_assert( ::std::is_same_v< decltype( switches[ 0 ]    ), switch_status &> );

boolとの間でキャストを受け入れる知恵について、あなた自身の意見があります。

enum class switch_status : bool { OFF = false, ON = true };

static_assert( static_cast< bool          >( switch_status::ON  ) == true               );
static_assert( static_cast< bool          >( switch_status::OFF ) == false              );
static_assert( static_cast< switch_status >( true               ) == switch_status::ON  );
static_assert( static_cast< switch_status >( false              ) == switch_status::OFF );
2
Tony E Lewis