C++ Weekly - Ep 265 - C++20's std::bit_cast

preview_player
Показать описание
☟☟ Awesome T-Shirts! Sponsors! Books! ☟☟

T-SHIRTS AVAILABLE!

WANT MORE JASON?

SUPPORT THE CHANNEL

GET INVOLVED

JASON'S BOOKS

► C++23 Best Practices

► C++ Best Practices

JASON'S PUZZLE BOOKS

► Object Lifetime Puzzlers Book 1

► Object Lifetime Puzzlers Book 2

► Object Lifetime Puzzlers Book 3

► Copy and Reference Puzzlers Book 1

► Copy and Reference Puzzlers Book 2

► Copy and Reference Puzzlers Book 3

► OpCode Puzzlers Book 1


RECOMMENDED BOOKS

AWESOME PROJECTS

O'Reilly VIDEOS

Рекомендации по теме
Комментарии
Автор

"You just can't convince people to use the memcpy version"

Too real, sadege

liangwang
Автор

Wow, now we can finally implement the quick inverse square root without evil bit-hacking!

jhuyt-
Автор

You can std::bit_cast a std::array<char, 4> to an into an int.
I kinda wish this supported ranges like memcpy, where you could copy a vector<char> size >= 4 to an int or something. Maybe they will add overloads in the future.
Noticed the thumbnail says std::bitcast instead of std::bit_cast.

Sebanisu
Автор

Who else loves seeing new videos from Jason?🙋‍♂️ I feel smarter instantly 😆

simonfarre
Автор

This is awesome, I've got to admit when encoding float's for network ordering I do abuse type punning to turn the float into a int32_t for encoding/decoding, now I can do it..."legally" lol.

LiquidWater
Автор

My understanding of strict aliasing in c is that it's basically the same as in C++, only that type punning though unions is allowed.
See footnote "95)" in the c11 standard.

oj
Автор

"Your code's broken regardless." That about sums up what Undefined Behavior (UB) is...

bettkitty
Автор

Are unions also not allowed in constexpr context? Because I recall that this used to be the "legal" way of doing that.

theIpatix
Автор

"std::bit_cast is designed partially to solve the problems that I talked about in my 'Stop Using reinterpret_cast!' video"
Unfortunately, bit_cast doesn't solve the problem outlined in that video at all. You can't bit_cast some contiguous bytes in memory to a struct. For that case you still have to use memcpy.

andrasbalogh
Автор

Afaik (but if it's different now.. I'll stand corrected) bitcast itself is doing the memcpy.

planetrift
Автор

Hack to implement next_after seems not weird in edge cases. Ex. when fraction part is (1.1...1)b and adding 1.
Or when fraction part is (1.0...0)b and substracting 1.

Can someone prove or disprove this?

However, example is ok.

danielmilyutin
Автор

I realy love the sound of your keyboard :) I will se if there is ASMR of that kind of sound.
And, of course, I like the content of your video.

chloelourseyre
Автор

I'm disappointed they didn't allow bit-casting references, which is what I thought the whole point would be when I first heard about bit_cast. As it stands, you still need to do what looks like a copy, and trust the compiler to optimize it away. That's the big stumbling block I've seen when trying to recommend using memcpy for type-punning; it looks less efficient. Only allowing value bit-casting doesn't change much, there.

kethernet
Автор

int is 16 bits on avr gcc/g++. Maybe interresting for the arduino folks.

ruadeil_zabelin
Автор

Jason: I'd use a union to do the conversion. It is cleaner than the C cast method.

void with_union() {
float f = 0.0032435435f;
union { float n; int i; } u;
u.n = f;
u.i += (f > 0 ? 1 : -1);

fmt::print("union {} -> {}\n", f, u.n);
}

GoatTheGoat
Автор

Time to rewrite Fast Inverse Square Root.

AddyGoesPlaces
Автор

I already use many warning/error flags, but if anything this convinced me to turn on every warning/error flag I didn't yet. Looking up the reason I see why, but I would never have thought the C version to be UB, the code makes logical sense.. I don't see why this is not an error without any additional flags. I'm also confused after reading type aliasing rules on cppref - it also applies to reinterpret cast, but it seems to make reinterpret cast useless - it is forbidden too use for every use case I can think of? Do I read right that not even type -> void, or void -> type is allowed? Is that not how serialization is often done?
* I overread the special case for char .. so, reinterpret cast is never allowed, unless it involves char or std::byte?

Shiwayari
Автор

Thanks! If you're doing C++20, why not use the new std::format?
Edit: never mind, i just see no compiler has implemented it yet :(

jhbonarius
Автор

This works with c++20, but not with c++17 🤔

constexpr float with_union(float input) {
union {
float f;
int i;
};
f = input;
i += (f > 0 ? 1 : -1);
return f;
}

Pakerwreah
Автор

It's funny how in your "Stop using reinterpret_cast" video, you used an example where you replaced a usage where `reinterpret_cast` was used to cast to a different pointer type, then referenced that `std::bit_cast` would be a better tool for the job. Then in this video you don't even address how one would go about using `std::bit_cast` in the same example.

But furthermore, maybe you aren't just converting from some array representation of bytes or ints to a single object, but converting from a range of one type to a range of a different type. In that case it seems like `std::bit_cast` can't be used, because it: 1, doesn't allow pointers and 2, returns by value. This specifically becomes an issue if you want to be able to assign to the converted types, like how in the previous video, you assigned back to the S type.

My guess would be that the answer to this limitation could be hidden somewhere in `std::ranges` land. That seems reasonable if one only needs read-access.

It seems like the proposed `std::bless` is the actual solution for this use case, which appears to have been renamed to `std::start_lifetime_as` in later revisions. It looks like this paper hasn't been included in the mailing since march 2020, so it's hard for me to judge where this is in the standardization process.

Tyranisaur