106 votes

Alternative à vector<bool>

Comme nous le savons tous (espérons-le), vector<bool> est totalement cassé et ne peut pas être traité comme un tableau C. Quelle est la meilleure façon d'obtenir cette fonctionnalité ? Jusqu'à présent, les idées auxquelles j'ai pensé sont les suivantes :

  • Utilisez un vector<char> à la place, ou
  • Utilisez une classe enveloppante et faites en sorte que vector<bool_wrapper>

Comment gérez-vous ce problème ? J'ai besoin de la c_array() fonctionnalité.

En guise de question secondaire, si je n'ai pas besoin des c_array() méthode, quelle est la meilleure façon d'aborder ce problème si j'ai besoin d'un accès aléatoire ? Devrais-je utiliser un deque ou autre chose ?

Edit :

  • J'ai besoin d'un dimensionnement dynamique.
  • Pour ceux qui ne le savent pas, vector<bool> est spécialisé de sorte que chaque bool prend 1 bit. Vous ne pouvez donc pas le convertir en un tableau de style C.
  • Je suppose que le terme "wrapper" est un peu mal choisi. Je pensais à quelque chose comme ça :

Bien sûr, alors je dois lire dans une my_bool en raison d'éventuels problèmes d'alignement :(

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

2 votes

Y a-t-il une raison de ne pas utiliser... un tableau de style C ?

0 votes

Rlbond, avez-vous besoin d'une taille dynamique ?

17 votes

Ok je vais mordre - pourquoi pensez-vous que le vecteur est ""totalement cassé"" ?

45voto

Daniel Earwicker Points 63298

Utilice std::deque si vous n'avez pas besoin du tableau, oui.

Sinon, utilisez une autre solution vector qui n'est pas spécialisé dans bool comme celle qui se trouve dans Boost Container .

26voto

Klaim Points 24511

C'est un problème intéressant.

Si vous avez besoin de ce qui aurait été un vecteur std::vector s'il n'était pas spécialisé, alors peut-être que quelque chose comme ça fonctionnerait bien dans votre cas :

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

J'ai essayé cela avec VC9 et cela semble fonctionner correctement. L'idée de la classe Bool est de simuler le type bool en fournissant le même comportement et la même taille (mais pas le même type). Presque tout le travail est fait par l'opérateur bool et les constructeurs de copie par défaut ici. J'ai ajouté un tri pour être sûr qu'il réagisse comme prévu lors de l'utilisation d'algorithmes.

Pas sûr que cela convienne à tous les cas. Si elle répond à vos besoins, ce serait moins de travail que de réécrire une classe de type vectoriel...

0 votes

"nous pourrions ajouter l'opérateur bool* & () { return &m_value ; }" - err. ISO : " sizeof(bool) n'est pas tenu d'être 1 "

3 votes

Je préférerais simplement changer le operator bool() const à un operator bool&() . Cela lui permet de mieux refléter le comportement d'un simple bool car il supporte l'affectation etc. dans des cas tels que v[0] = true; Je ne vois vraiment pas de problème avec ce changement, alors puis-je faire la modification ?

21voto

Cela dépend de vos besoins. Je choisirais soit std::vector<unsigned char> . L'écriture d'un wrapper peut convenir si vous n'utilisez qu'un sous-ensemble de la fonctionnalité, sinon cela deviendra un cauchemar.

0 votes

unsigned char est toujours un seul octet alors que uint8_t peut ne pas être pris en charge par l'implémentation. uint_fast8_t pourrait fonctionner si l'intention est d'indiquer clairement qu'il s'agit d'un seul octet et non d'un caractère, mais vous pourriez tout aussi bien utiliser std::byte puis

16voto

Evgeny Panasyuk Points 5408

Comment gérez-vous ce problème ? J'ai besoin de la fonctionnalité c_array().

boost::container::vector<bool> :

vecteur < bool > Cette spécialisation a été assez problématique, et plusieurs tentatives infructueuses ont été faites pour la déprécier ou la supprimer de la norme. Boost.Container ne le met pas en œuvre car il existe un système supérieur Boost.DynamicBitset solution.

...

Así que boost::container::vector::iterator renvoie de vraies références bool et fonctionne comme un conteneur entièrement conforme. Si vous avez besoin d'une version optimisée en termes de mémoire de boost::container::vector < bool > fonctionnalités, veuillez utiliser Boost.DynamicBitset .

6voto

AHelps Points 1171

Pensez à utiliser un vector< int >. Une fois que vous avez dépassé la compilation et la vérification des types, bool et int ne sont que des mots machine (edit : apparemment ce n'est pas toujours vrai ; mais ce sera vrai sur de nombreuses architectures PC). Dans les cas où vous voulez convertir sans avertissement, utilisez "bool foo = !!bar", qui convertit zéro en faux et un non-zéro en vrai.

Un vecteur< char > ou similaire utilisera moins d'espace, bien qu'il ait également le potentiel de prendre un (très petit) coup de vitesse dans certaines circonstances, parce que les caractères sont moins que la taille du mot machine. C'est, je crois, la raison principale pour laquelle les bools sont implémentés en utilisant des ints au lieu de chars.

Si vous voulez vraiment une sémantique propre, j'aime aussi la suggestion de faire votre propre classe booléenne -- ressemble à un bool, agit comme un bool, mais trompe la spécialisation du modèle.

Aussi, bienvenue dans le club des personnes qui veulent que la spécialisation vector< bool > soit supprimée de la norme C++ (avec bit_vector pour la remplacer). C'est là que tous les jeunes cool traînent :).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X