2015-05-12 20 views
19

Mam następujący kod:Dlaczego auto jest wyprowadzona do int zamiast uint16_t

uint16_t getLastMarker(const std::string &number); 
... 
const auto msgMarker = getLastMarker(msg.number) + static_cast<uint16_t>(1); 
static_assert(std::is_same<decltype(msgMarker), const int>::value, "Should fail"); 
static_assert(std::is_same<decltype(msgMarker), const uint16_t>::value, "Should not fail"); 

i spodziewam się, że pierwsze twierdzenie nie powiedzie się, a drugi nie. Jednak gcc 4.9.2 i clang 3.6 działają odwrotnie. Jeśli użyję uint16_t zamiast auto w moim kodzie, to poprawne stwierdzenie nie powiedzie się, a drugie się powiedzie.

P.S. Początkowo miałem tylko 1 zamiast static_cast<uint16_t>(1) i uważałem, że problem jest spowodowany tym, że numeryczny literał 1 ma typ int, ale błędny asercja nie działa nawet po jawnym rzutowaniu tutaj.

+11

Powiązane [Dlaczego krótki musi być konwertowany na int przed operacjami arytmetycznymi w C i C++?] (Http://stackoverflow.com/q/24371868/1708801) –

+4

Kolejny przykład "nie używaj' auto' wszędzie". – Shoe

Odpowiedz

16

Dodawanie wykona usual arithmetic conversions na jej argumentów, które w tym przypadku spowoduje argumentów awansować int należytym The integer promotions i wynik będzie również int.

Możesz użyć uint16_t zamiast automatycznego, aby wymusić konwersję z powrotem lub w ogólnym przypadku możesz użyć static_cast.

Aby uzasadnić, dlaczego typ mniejszy niż , int są promowane do większych typów zobacz Why must a short be converted to an int before arithmetic operations in C and C++?.

Dla porównania, z projektu C++ standardowej sekcji 5.7addytywne operatorzy:

[...] Zwykłe arytmetyczne konwersji wykonana operandy arytmetycznej lub wyliczania typu [...]

oraz części 5Ekspresja:

[...] W przeciwnym razie całkowe promocje (4.5) będą wykonywane na obu operandach. to następujące zasady stosuje się do promowanych argumentów [...]

oraz części 4.5Integralne Gorące (nacisk kopalni):

prvalue z typ całkowity inny niż bool, char16_t, char32_t lub wchar_t , którego całkowity stopień konwersji (4.13) jest mniejszy niż pozycja z int może być przekonwertowana na wartość prynktu int, jeśli int może reprezentować wszystkie wartości typu źródła; w przeciwnym razie wartość prinalue źródła może zostać przekonwertowana na prvalue typu unsigned int.

Zakładając int jest większy niż 16-bitowy.

8

Operacje arytmetyczne nie działają na żadnym typie mniejszym niż int.Tak więc, jeśli uint16_t jest mniejsza niż int, będzie to promowane do int (lub ewentualnie większy typ, jeśli jest to konieczne, aby dopasować drugi operand) przed wykonaniem dodawania.

Wynikiem dodania będzie typ promowany. Jeśli chcesz innego typu, musisz później dokonać konwersji.