#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&
?それともコンパイラのバグですか?
または、私は愚かなことを試みていますか? :)
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>
の特殊化されていないバージョンを持っています。
あなたの期待は正常ですが、問題はstd::vector<bool>
は、C++委員会による一種の実験です。これは実際には、メモリに密にパックされたブール値(値ごとに1ビット)を格納するテンプレートの特殊化です。
そして、あなたは少し参照することができないので、あなたの問題があります。
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
std::vector<bool>
は適合しないコンテナです。スペースを最適化するために、bool
sをパックし、参照を提供できません。
使用する - boost::dynamic_bitset
代わりに。
ちょうど私の2セント:
std::vector<bool>::reference
はstruct _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)に変更しました。
bool
を含む構造を作成し、その構造型を使用して_vector<>
_を作成します。
試してください:
_vector<struct sb>
_ sb
は_struct {boolean b];
_です
その後、あなたは言うことができます
Push_back({true})
行う
_typedef struct sbool {bool b;} boolstruct;
_、次に_vector<boolstruct> bs;
_