2016-11-23 1 views
4

Considérez le code suivant:différence de comportement Situés entre libstdC++ et libC++: opérateur >> sur bitset

#include <bitset> 
#include <sstream> 
#include <iostream> 

int main(int argc, char* argv[]) 
{ 
    std::stringstream stream; 
    std::bitset<1> bitset(1); 
    std::cout<<"before = "<<bitset[0]<<std::endl; 
    stream<<"4"; 
    stream>>bitset; 
    std::cout<<"after = "<<bitset[0]<<std::endl; 
    return 0; 
} 

Compilé sous g++ avec libstdc++, le résultat est:

> g++ bitset_empty.cpp -o bitset_empty 
> ./bitset_empty 
before = 1 
after = 1 

Compilé sous clang++ avec libc++ , le résultat est:

> clang++ -stdlib=libc++ bitset_empty.cpp -o bitset_empty 
> ./bitset_empty 
before = 1 
after = 0 

Lequel a raison? Les deux (à cause d'un comportement indéfini?)? GCC? Bruit?

Répondre

2

De ma compréhension, libC++ est ici, mais ce n'est pas le seul comportement correct.

N4140 §20.6.4 [bitset.operators]

Effets: extraits à partir de N caractères est. Stocke ces caractères dans un objet temporaire str de type basic_string<charT, traits>, puis évalue l'expression x = bitset<N>(str). Les caractères sont extraits et stockés jusqu'à ce que l'un des événements suivants se produise:

  • Les caractères N ont été extraits et stockés;
  • de fin de fichier se produit sur la séquence d'entrée;
  • le caractère d'entrée suivante est ni is.widen(’0’) ni is.widen(’1’) (dans ce cas, le caractère d'entrée n'est pas extrait).

Si aucun caractère sont stockés dans str, les appels is.setstate(ios_base::failbit) (qui peut jeter ios_base::failure (27.5.5.4))

Il est important de noter que x = bitset<N>(str) n'est pas conditionnelle. Si ios_base::failure n'est pas lancé, alors c'est l'expression exécutée. Et bitset<N>(""s) (c'est-à-dire d'une chaîne vide) est 0.

Ainsi, dans ma compréhension, votre bitset devrait être remis à zéro ou aurait dû être jeté à l'exception mentionnée ci-dessus.

Si aucune exception est levée, vous pouvez tester si votre opération a réussi (en testant le flux de retour).

2

Vous devriez vérifier si

stream>>bitset; 

réussit. Si ce n'est pas le cas, vous ne pouvez pas compter sur la valeur de bitset après cela.

#include <bitset> 
#include <sstream> 
#include <iostream> 

int main(int argc, char* argv[]) 
{ 
    std::stringstream stream; 
    std::bitset<1> bitset(1); 
    std::cout<<"before = "<<bitset[0]<<std::endl; 
    stream<<"4"; 
    if (stream>>bitset) 
    { 
     std::cout<<"after = "<<bitset[0]<<std::endl; 
    } 
    else 
    { 
     std::cout << "Failed to restore bitset from stream.\n"; 
    } 
    return 0; 
} 

sortie en utilisant g ++ 4.9.3:

before = 1 
Failed to restore bitset from stream.