Date: Wed, 24 Apr 2019 20:22:45 +0200
Mohamed Khaled via Std-Discussion wrote:
> ```
> #include <type_traits>
> #include <iostream>
>
> struct C
> {
> uint32_t x : 2;
> bool y : 2;
> };
>
> void f(int)
> {
> std::cout << "void f(int)" << std::endl;
> }
>
> void f(uint32_t)
> {
> std::cout << "void f(uint32_t)" << std::endl;
> }
>
> int main()
> {
> C c{0b1};
>
> std::cout << (static_cast<uint32_t>(0b1) << 31) << std::endl;
> std::cout << (c.x << 31) << std::endl;
> std::cout << (c.x << 10) << std::endl;
> f(c.x);
> std::cout << std::boolalpha << std::is_same_v<decltype(c.x), uint32_t>
> << std::endl;
> std::cout << std::boolalpha << std::is_same_v<decltype(c.y), bool> <<
> std::endl;
> }
> ```
>
> Output
> ```
> 2147483648
> -2147483648
> 1024
> void f(uint32_t)
> true
> true
> ```
>
> Hi all,
>
> My question is regarding the return type of accessing bitfields. I have
> learned that for built-in arithmetic operators, numeric promotion takes
> place instead of using the type declared inclass. I find this very
> confusing that c.x is treated as int despite being declared as uin32_t and
> to add more to the confusion the static type check resolves to uint32 and
> naturally the overload resolution. Is there a reason for this inconsistent
> behaviour?
>
> Regards,
> Mohamed
That's because of integer promotion. A related problem: short + short == int. I believe the reason for this is that you don't lose precision when working with small types. Since int can cover every value of a uint32_t:2, it is safe to do this conversion. You can find the rules for this here: http://eel.is/c++draft/conv.prom
This integer promotion doesn't happen everywhere, namely only but when arithmetic. That's why you get a uint32_t during overload resolution and decltype.
> ```
> #include <type_traits>
> #include <iostream>
>
> struct C
> {
> uint32_t x : 2;
> bool y : 2;
> };
>
> void f(int)
> {
> std::cout << "void f(int)" << std::endl;
> }
>
> void f(uint32_t)
> {
> std::cout << "void f(uint32_t)" << std::endl;
> }
>
> int main()
> {
> C c{0b1};
>
> std::cout << (static_cast<uint32_t>(0b1) << 31) << std::endl;
> std::cout << (c.x << 31) << std::endl;
> std::cout << (c.x << 10) << std::endl;
> f(c.x);
> std::cout << std::boolalpha << std::is_same_v<decltype(c.x), uint32_t>
> << std::endl;
> std::cout << std::boolalpha << std::is_same_v<decltype(c.y), bool> <<
> std::endl;
> }
> ```
>
> Output
> ```
> 2147483648
> -2147483648
> 1024
> void f(uint32_t)
> true
> true
> ```
>
> Hi all,
>
> My question is regarding the return type of accessing bitfields. I have
> learned that for built-in arithmetic operators, numeric promotion takes
> place instead of using the type declared inclass. I find this very
> confusing that c.x is treated as int despite being declared as uin32_t and
> to add more to the confusion the static type check resolves to uint32 and
> naturally the overload resolution. Is there a reason for this inconsistent
> behaviour?
>
> Regards,
> Mohamed
That's because of integer promotion. A related problem: short + short == int. I believe the reason for this is that you don't lose precision when working with small types. Since int can cover every value of a uint32_t:2, it is safe to do this conversion. You can find the rules for this here: http://eel.is/c++draft/conv.prom
This integer promotion doesn't happen everywhere, namely only but when arithmetic. That's why you get a uint32_t during overload resolution and decltype.
-- - Nicolas
Received on 2019-04-24 13:24:26