vector <bool>の代替


90

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

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

どうやってこの問題を処理しますか?c_array()機能が必要です。

余談ですが、このc_array()方法が必要ない場合、ランダムアクセスが必要な場合にこの問題に取り組む最善の方法は何ですか?両端キューなどを使用する必要がありますか?

編集:

  • 動的なサイズ設定が必要です。
  • 知らない人のvector<bool>ために、それぞれboolが1ビットを取るように専門化されています。したがって、それをCスタイルの配列に変換することはできません。
  • 「ラッパー」はちょっと誤称だと思います。私はこのようなことを考えていました:

もちろん、my_boolアライメントの問題が発生する可能性があるため、次に読む必要があります:(

struct my_bool
{
    bool the_bool;
};
vector<my_bool> haha_i_tricked_you;

2
Cスタイルの配列を使用しない理由はありますか?
kquinn 2009年

rlbond、動的サイズが必要ですか?
ヨハネスシャウブ-litb

16
さあ、噛みます-ベクトルが「完全に壊れている」と思うのはなぜですか?
Andrew Grant


4
興味深いことに、vector<bool>さまざまなスレッドがベクトル内のさまざまな要素を同時に安全に変更できると期待していたため、コードでデータ競合のバグが発生しました。を使用して解決されましたdeque<bool>
Andres Riofrio 2013年

回答:



21

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

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* 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 *演算子&(){return&m_value;}を追加できます"-エラー。ISO: "でsizeof(bool)ある必要はありません1"
Evgeny Panasyuk 2013

2
私は単純に変更することを好むだろうoperator bool() constoperator bool&()。これにより、割り当てのサポートなど、単純なブールの動作がよりよく反映されます。v[0] = true;この変更で問題が実際に見えない場合などに、編集を行うことができますか?
Agentlien 2014年

19

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


unsigned charuint8_t実装ではサポートされていない可能性がありますが、常に1バイトです。uint_fast8_t意図は、それはそれは単一バイトではなく文字ですが、あなたにも使用することがあります明らかにすることをである場合にかかわらず、働くことができstd::byte、その後
ガブリエルRavier

13

どうやってこの問題を処理しますか?c_array()機能が必要です。

boost::container::vector<bool>

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

...

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


6

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

vector <char>または同様のものは、使用するスペースが少なくなりますが、文字はマシンのワードサイズよりも小さいため、状況によっては(非常に小さい)スピードヒットが発生する可能性もあります。これが、ブールの代わりに文字ではなく整数を使用して実装される主な理由です。

クリーンなセマンティクスが本当に必要な場合は、独自のブールクラスを作成するという提案も気に入っています。ブールのように見え、ブールのように機能しますが、テンプレートの特殊化はばかです。

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


4

この問題はcomp.lang.c ++。moderatedですでに説明されています。提案されるソリューション:

  • 独自のアロケータ(に基づくstd::allocator)と独自のベクトル特殊化。
  • 使用std::deque(早い段階でS.メイヤーズの本の1つで推奨されていました)-ただし、これは要件ではありません。
  • POD boolラッパーを作成します。
  • 代わりに同じサイズの何か(char/ int/ etc)を使用してください。 boolbool

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

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


3

最も簡単な答えは使用されています。その後、あなたは言うことができます。良いように思える。vector<struct sb>sbstruct {boolean b};push_back({true})


2

私が推奨する回避策は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 );
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.