web-dev-qa-db-ja.com

vector <bool> :: referenceがboolへの参照を返さないのはなぜですか?

#include <vector>

struct A
{
    void foo(){}
};

template< typename T >
void callIfToggled( bool v1, bool &v2, T & t )
{
    if ( v1 != v2 )
    {
        v2 = v1;
        t.foo();
    }
}

int main()
{
    std::vector< bool > v= { false, true, false };

    const bool f = false;
    A a;

    callIfToggled( f, v[0], a );
    callIfToggled( f, v[1], a );
    callIfToggled( f, v[2], a );
}

上記の例をコンパイルすると、次のエラーが発生します。

dk2.cpp: In function 'int main()':
dk2.cpp:29:28: error: no matching function for call to 'callIfToggled(const bool&, std::vector<bool>::reference, A&)'
dk2.cpp:29:28: note: candidate is:
dk2.cpp:13:6: note: template<class T> void callIfToggled(bool, bool&, T&)

次のようにg ++(バージョン4.6.1)を使用してコンパイルしました。

g++ -O3 -std=c++0x -Wall -Wextra -pedantic dk2.cpp

問題はなぜこれが起こるのですか? vector<bool>::referenceないbool&?それともコンパイラのバグですか?
または、私は愚かなことを試みていますか? :)

57
BЈовић

ベクターはブールに特化しています

Stdのミスと考えられます。代わりにvector<char>を使用してください:

template<typename t>
struct foo {
  using type = t;
};
template<>
struct foo<bool> {
  using type = char;
};

template<typename t, typename... p>
using fixed_vector = std::vector<typename foo<t>::type, p...>;

場合によっては、ベクター内に含まれるブールへの参照が必要になることがあります。残念ながら、vector<char>を使用すると、charへの参照しか得られません。 bool&が本当に必要な場合は、 Boost Containersライブラリ を確認してください。それはvector<bool>の特殊化されていないバージョンを持っています。

58
Pubby

あなたの期待は正常ですが、問題はstd::vector<bool>は、C++委員会による一種の実験です。これは実際には、メモリに密にパックされたブール値(値ごとに1ビット)を格納するテンプレートの特殊化です。

そして、あなたは少し参照することができないので、あなたの問題があります。

49
rodrigo

std::vector< bool >はその内容をパックして、各ブール値が1ビット、8ビットから1バイトに格納されるようにします。これはメモリ効率が良いですが、プロセッサは要求されたビットにアクセスするために算術を実行する必要があるため、計算量が多くなります。また、バイト内のビットはC++オブジェクトモデルでアドレスを持たないため、bool参照またはポインタセマンティクスでは機能しません。

std::vector<bool>::reference型の変数を宣言して、bool&であるかのように使用できます。これにより、汎用アルゴリズムに互換性を持たせることができます。

std::vector< bool > bitvec( 22 );
std::vector< bool >::reference third = bitvec[ 2 ];
third = true; // assign value to referenced bit

C++ 11では、autoおよび&&指定子を使用してこれを回避できます。これは、ベクター要素にバインドされた左辺値参照または一時的にバインドされた右辺値参照を自動的に選択します。

std::vector< bool > bitvec( 22 );
auto &&third = bitvec[ 2 ]; // obtain a std::vector< bool >::reference
third = true; // assign value to referenced bit
15
Potatoswatter

std::vector<bool>は適合しないコンテナです。スペースを最適化するために、boolsをパックし、参照を提供できません。

使用する - boost::dynamic_bitset 代わりに。

15
reder

ちょうど私の2セント:

std::vector<bool>::referencestruct _Bit_referenceのtypedefであり、次のように定義されます。

typedef unsigned long _Bit_type;

struct _Bit_reference
  {
    _Bit_type * _M_p;
    _Bit_type _M_mask;

    // constructors, operators, etc...

    operator bool() const
    { return !!(*_M_p & _M_mask); }
  };

このように関数を変更すると機能します(まあ、少なくともコンパイルはテストしていません)。

template< typename T >
void callIfToggled( bool v1, std::vector<bool>::reference v2, T & t )
{
    bool b = v2;  
    if ( v1 != b )
    {
        v2 = v1;
        t.foo();
    }
}

編集:私は条件を(v1!= v2)から(良い考えではなかった)から(v1!= b)に変更しました。

5
jrok

boolを含む構造を作成し、その構造型を使用して_vector<>_を作成します。

試してください:

_vector<struct sb>_ sbは_struct {boolean b];_です

その後、あなたは言うことができます

Push_back({true})

行う

_typedef struct sbool {bool b;} boolstruct;_、次に_vector<boolstruct> bs;_

1
Todd