Por que o vetor :: reference não retorna referência ao bool?

#include  struct A { void foo(){} }; template void callIfToggled( bool v1, bool &v2, T & t ) { if ( v1 != v2 ) { v2 = v1; t.foo(); } } int main() { std::vector 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 ); } 

A compilation do exemplo acima produz o próximo erro:

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

Eu compilei usando g ++ (versão 4.6.1) assim:

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

A questão é por que isso acontece? O vector::reference é vector::reference não bool& ? Ou é um bug do compilador?
Ou estou tentando algo estúpido? 🙂

   

O vetor é especializado em bool .

Considera-se um erro do std. Use o vector vez disso:

 template struct foo { using type = t; }; template<> struct foo { using type = char; }; template using fixed_vector = std::vector::type, p...>; 

Ocasionalmente, você pode precisar de referências a um bool contido dentro do vetor. Infelizmente, usar o vector só pode fornecer referências a caracteres. Se você realmente precisa bool& , confira a biblioteca Boost Containers . Tem uma versão não especializada do vector .

Suas expectativas são normais, mas o problema é que std::vector tem sido uma espécie de experimento pelo comitê de C ++. Na verdade, é uma especialização de modelo que armazena os valores de bool bem compactados na memory: um bit por valor.

E desde que você não pode ter uma referência a um pouco, há o seu problema.

std::vector é um contêiner não-conforme. Para otimizar o espaço, ele embala bool s e não pode fornecer referência.

Use boost::dynamic_bitset vez disso.

std::vector< bool > empacota seu conteúdo para que cada valor booleano seja armazenado em um bit, oito bits em um byte. Isso é eficiente em termos de memory, mas computacionalmente intensivo, já que o processador deve executar aritmética para acessar o bit solicitado. E não funciona com referência bool ou semântica de pointers, pois os bits dentro de um byte não possuem endereços no modelo de object C ++.

Você ainda pode declarar uma variável do tipo std::vector::reference e usá-la como se fosse bool& . Isso permite que algoritmos genéricos sejam compatíveis.

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

Em C ++ 11, você pode contornar isso usando auto e o especificador && que seleciona automaticamente uma referência de lvalue vinculada ao elemento vector ou uma referência de rvalue ligada a um temporário.

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

Apenas meus 2 centavos:

std::vector::reference é um typedef para struct _Bit_reference que é definido como

 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); } }; 

Mudando a function assim, funciona (bem, compila pelo menos, não testei):

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

EDIT: eu mudei a condição de (v1! = V2), o que não era uma boa idéia, para (v1! = B).

Faça uma estrutura com um bool e faça o vector<> usando esse tipo de estrutura.

Experimentar:

vector onde sb é struct {boolean b];

então você pode dizer

push_back({true})

Faz

typedef struct sbool {bool b;} boolstruct; e depois vector bs;