Consideriamo la funzione (una delle possibili implementazioni di esso) che azzererebbe correttamente N bit di un valore corto senza segno (o qualsiasi altro tipo integrale senza segno). Il possibile implementazione potrebbe apparire come segue:Bit bit shifting e scartare bit
template<unsigned int shift>
unsigned short zero_right(unsigned short arg) {
using type = unsigned short;
constexpr type mask = ~(type(0));
constexpr type right_zeros = mask << shift; // <-- error here
return arg & right_zeros;
}
int check() {
return zero_right<4>(16);
}
Con questo codice, tutti i compilatori ho accesso a lamentarsi, in un modo o nell'altro, su possibili troppo pieno. Clang è il più esplicito, con seguente messaggio chiaro:
error: implicit conversion from 'int' to 'const type' (aka 'const unsigned short') changes value from 1048560 to 65520 [-Werror,-Wconstant-conversion]
Questo codice è ben definito e chiaro come il sole per me, ma quando 3 compilatori si lamentano, sto diventando molto nervoso. Mi sto perdendo qualcosa qui? C'è davvero una possibilità che qualcosa di strano stia succedendo?
P.S. Mentre le implementazioni alternative di zeriong out X bits a sinistra potrebbero essere benvenute e interessanti, l'obiettivo principale di questa domanda è la validità del codice come postata.
@TavianBarnes, non possono essere promossi a int firmati per argomenti senza segno. – SergeyA
Non è quello che stai chiedendo, ma qualcosa di cui potresti voler essere a conoscenza (e non fare attenzione) è che se hai lasciato shift un intero senza segno con 'n' bit dove 'n' è> = il numero di bit in il tipo che si sposta, quindi quello è il comportamento non definito. –
@SergeyA Ma questo è ancora il problema: il risultato w di '<<' è int, non breve. Convertire il risultato di 'maschera << shift' in' type' prima che l'assegnazione faccia scomparire l'errore. –