C++ Weekly - Ep 254 - C++23's signed / unsigned size_t Literals
Vložit
- čas přidán 28. 05. 2024
- ☟☟ Awesome T-Shirts! Sponsors! Books! ☟☟
Upcoming Workshop: Understanding Object Lifetime, C++ On Sea, July 2, 2024
► cpponsea.uk/2024/sessions/und...
Upcoming Workshop: C++ Best Practices, NDC TechTown, Sept 9-10, 2024
► ndctechtown.com/workshops/c-b...
T-SHIRTS AVAILABLE!
► The best C++ T-Shirts anywhere! my-store-d16a2f.creator-sprin...
WANT MORE JASON?
► My Training Classes: emptycrate.com/training.html
► Follow me on twitter: / lefticus
SUPPORT THE CHANNEL
► Patreon: / lefticus
► Github Sponsors: github.com/sponsors/lefticus
► Paypal Donation: www.paypal.com/donate/?hosted...
GET INVOLVED
► Video Idea List: github.com/lefticus/cpp_weekl...
JASON'S BOOKS
► C++23 Best Practices
Leanpub Ebook: leanpub.com/cpp23_best_practi...
► C++ Best Practices
Amazon Paperback: amzn.to/3wpAU3Z
Leanpub Ebook: leanpub.com/cppbestpractices
JASON'S PUZZLE BOOKS
► Object Lifetime Puzzlers Book 1
Amazon Paperback: amzn.to/3g6Ervj
Leanpub Ebook: leanpub.com/objectlifetimepuz...
► Object Lifetime Puzzlers Book 2
Amazon Paperback: amzn.to/3whdUDU
Leanpub Ebook: leanpub.com/objectlifetimepuz...
► Object Lifetime Puzzlers Book 3
Leanpub Ebook: leanpub.com/objectlifetimepuz...
► Copy and Reference Puzzlers Book 1
Amazon Paperback: amzn.to/3g7ZVb9
Leanpub Ebook: leanpub.com/copyandreferencep...
► Copy and Reference Puzzlers Book 2
Amazon Paperback: amzn.to/3X1LOIx
Leanpub Ebook: leanpub.com/copyandreferencep...
► Copy and Reference Puzzlers Book 3
Leanpub Ebook: leanpub.com/copyandreferencep...
► OpCode Puzzlers Book 1
Amazon Paperback: amzn.to/3KCNJg6
Leanpub Ebook: leanpub.com/opcodepuzzlers_book1
RECOMMENDED BOOKS
► Bjarne Stroustrup's A Tour of C++ (now with C++20/23!): amzn.to/3X4Wypr
AWESOME PROJECTS
► The C++ Starter Project - Gets you started with Best Practices Quickly - github.com/cpp-best-practices...
► C++ Best Practices Forkable Coding Standards - github.com/cpp-best-practices...
O'Reilly VIDEOS
► Inheritance and Polymorphism in C++ - www.oreilly.com/library/view/...
► Learning C++ Best Practices - www.oreilly.com/library/view/... - Věda a technologie
This will fix one of the most annoying things in my day-to-day C++
True dat!
I'am still waiting for static type reflection. Hope it'll make it into the c++23
I have custom literals in my codebase for exactly this. I called them _size_t and _ssize_t. I'm glad they're going to be a standard.
Не успел перейти на С++20, уже 23
I missed the "literals" part of the title when i saw the video notification. Now, it makes more sense!
It should have been in c++17 already. What took so long :)
Hello Jason! I am a big fan of C++ Weekly, it has helped me learn so much more about C++ than I had ever hoped to know.
I am just wondering if you ever covered C++20 modules? I can't seem to find a video when searching, and while I have had a look at what cppreference has about modules your videos often go into the small details that are easy to miss and give great examples.
I haven't made any videos on modules yet because I'm still waiting on good compiler support.
@@cppweekly Ah, that makes sense 😅
confused: size_t is already unsigned, why is there an unsigned qualifier? ptrdiff_t is accepted as the signed counterpart to size_t. The z and t format specifiers are already accepted in printf() since C++11.
I suppose since size_t is implementation-defined, some perverse implementor could decide on a type that allows negative sizes?
indeed. I think the fact that the committee have left both types to be implementation-defined means that they have to make explicit the programmer's intention within the context of their pointer and size definitions. The **convention** is that size_t is unsigned and ptrdiff_t is signed, but there is nothing to say you can't redefine them to any underlying types - or widths - you wish.
sometimes it's useful to have a negative size, indicates an invalid size. This was used a lot in c with string sizes. If string is zero-terminated, then one could pass -1 as the string length. Not really a c++ thing to do, but still
@@treyquattro No, the standard does define that size_t is unsigned and ptrdiff_t is signed. (These requirements may not be spelled out specifically for the typedefs, but they are spelled out in the definitions of the sizeof and - operators.) The issue at hand is instead that the standard does *not* require them to be of the same width, which is brought up in the paper and visible onscreen in this video if you pause at 2:43. Signed sizes are indeed useful, and when they added span they also added ssize() functions for all the other containers, but that's a separate matter from the meanings of 0z and 0ut.
What am I missing? Why would someone want to use auto on the lhs and then explicitly name the type on the rhs?
Very useful. Allows using `auto` everywhere like `let` in Rust.
It's already almost like that, but that's not a very good idea, C++ is a statically typed language using 'auto' everywhere just hides useful information
@@samu6982 Rust and many other languages are statically typed too. C++ is no different. You don't need to write something that the compiler already knows.
Not the same, but related: working with Qt and the standard library in the same project (so basically every Qt project), with any sort of sensible set of warnings enabled your code is covered in static_casts to and from int and size_t :(. (That are no doubt hiding lots of subtle bugs when containers get large.)
Yeah, Qt is kind of infuriating with haphazard int's where they meant size_t's. If you want to compile your code with C++17 or later and have all warnings on, it helps to surround every Qt header include with `#pragma warning(push, 0)` ... `#pragma warning(pop)` or your warning spam will be intense even with Qt6. Unless it's part of your job to verify the library is working correctly, which I wouldn't envy.
Great content! However the animations between cuts are a bit wordarty ;)
c++ is getting crazy
FINALLY. I am so tired of having to use size_t instead of auto in variable declarations when working with STL collections and manual algorithms.
Is there any advantage of using `static_cast(32)` over `std::size_t(32)`?
Yes, and no. I would use `std::size_t{32}` instead. `std::size_t(32)` is actually a c-style cast and will do any conversion that's possible, and this could be bad if you made a typo. The braced-init version should prevent (at compile time) any lossy conversion.
@@cppweekly What? No, it's not a C-style cast. A C-style cast would be (std::size_t)32. std::size_t(32) is a C++ constructor call, a C compiler will reject size_t(32).
@@tjthill For fundamental types it is a C-cast. For classes it is not always a constructor call - might be a conversion.
could you please provide the url of the site which you referred to @31 secs ?
That's en.cppreference.com/w/cpp/compiler_support
@@HiAdrian Thanks a lot
It seems like given the current revision the EWG accepted z/zu but rejected t/tu, so we're getting one but not the other? Rather curious choice since I think there will definitely be confusion as to why z != ptrdiff_t, even if the paper does justify why that is the case.
both size_t and ptrdiff_t are implementation-defined but are anticipated to be unsigned and signed respectively. I would expect z == tu if you somehow needed to then have an unsigned ptrdiff_t. The fact that they are implementation-defined complicates the situation and I suppose means they have to include zu and tu to make it explicit.
@@treyquattro I agree, and maybe I wasn't totally clear, but my confusion was more on the side of why one was accepted and not the other -- seems like it'll just lead to more confusion that way and a longer adaptation time to using these.
In practice I think maybe I would just use z/uz until we end up with a definitive type for ptrdiff_t given they're equivalent on most systems, but it's a bit annoying that we won't have both (assuming my read of the proposal is right).
Jason, what's your favorite C++ feature?
LOL isn't is obvious? Lambdas.
You passed `-std=c++2a` to the compiler. Do the compilers accept `-std=c++2b` already?
Hm, not sure on that. I like how for msvc it's just `c++latest` to use whatever is the newest, even if you don't know newest postfix.
Nice video. What would be the use case of an unsigned size_t do you think?
Edit: oops I meant signed size_t
I mean. A size of a type can't be negative. Neither can the number of elements in a container/array/buffer. I know some committee members are like "everything should be signed", but I disagree.
@@lincolnsand5127 oops I meant signed size_t. For the reasons you mentioned, I’m trying to imagine when it could ever be used ever. Like is it purely a theoretical type?
@@adamshield5029 You can use the negative numbers to encode errors
@@adamshield5029 if (ssize(range1) - ssize(range2) < 0) is a slightly contrived example of where signed sizes makes a difference, but something slightly more elaborated could easily come up in normal code.
For instance, if you write a loop which does something with "extra" elements at the end of one range, using the difference of their sizes for the loop condition variable with a < comparison would make sense, and with signed sizes, it would not run the loop at all if the difference is negative, but with unsigned sizes, it would run the loop an absurdly large number of times and very probably cause UB.
When you subtract two sizes now, if you haven't already made sure to subtract small from large, the result is meaningless (Well, you could compare it with numeric_limits::max()/2 to get the same effect as seeing if it's negative, but that is hideous.) But with a signed size, the result behaves exactly as you would expect.
size_t can be kinda evil if one's not careful cross compiling between 32/64 bits. Always storing the result of .size() into a uint64_t is the simplest way to be sure I won't mess up. Also what's wrong with: auto val = (uint64_t)myvec.size(). I only use uint[size]_t s to store integers.
This is the opposite of what I would recommend. If you always force it into a 64bit integer you're going to cause other headaches and performance pessimizations on 32bit platforms. If you use size_t and/or auto consistently you won't have any risk of that.
@@cppweekly I agree. Still if you developed something relatively big for 32bits, and sometime later you ported it to 64bits, and the app crashed and you couldn't find where the bug is, check if by any chance you're assigning a size_t to a 32bits varible. I ran exactly into this and I don't remember if it was an explicit cast and the compiler didin't warn me or if I simply ignored the warning but after debugging it I got a bitter taste in my mouth that it could have been much harder to find in other circumstances..
Why is that considered a 'core language feature'? For me it looks like some user-defined literals which can be provided by the STL.
Because it's not an user-defined literals and it won't be defined in the STL. You will be able to use it without including any file or using any namespace.
is size_t becoming a language feature then? i.e. a keyword instead of a typedef
someone should just make a proposal already. And some compilers already have that feature, like msvc
No, the core language way to spell it will remain some variation on `decltype(sizeof(int))` (and std::ptrdiff_t is something like `decltype(static_cast(nullptr) - static_cast(nullptr))`, for comparison). There's no reason to make the typedefs keywords.
@@killerbee.13 well we wouldn't need to qualify them using the std namespace anymore .. 5 characters less
@@jbar7742 I mean, you don't really have to now on most implementations, because they're almost always declared in C headers in the root namespace. But even besides that, you can `using std::size_t;` if you want.
@@killerbee.13 well there is no guarantee that they do so, and and a global using declaration is meh
finally
What about that all this types are aliases. It gets really nasty if they map to different integer types on different platforms. Like this long long vs long problem. Every time I explain it to novices they ask me way the int32_t is an alias to int not the other way around. Maybe it was a smart idea in the seventies but today it is a bug source. 😏 With modules they should provide a sane integer behavior which you can opt in per file. 😉
Why 'z' though? Why not just use 's' instead?
it's already the suffix for shorts
@gbnam8 there're no suffixes for short types. But a lot of suffixes have migrated from printf identifier specs. And %s is a string, not a size_t
s is string
@@Arganoid Also seconds
@@Arganoid Yes, but it could be overloaded for unsigned long long type.
why is everyone so afraid of c-casts? Unless u cast pointer/reference values to another pointer/reference type then it's 100% safe and much more readable. Ofc 32uz is shorter even comparing to (size_t)32, but still.
c-style casts can convert almost anything to almost anything else. They are worse than `reinterpret_cast`. If you want to go down this road, then you should use the braced-init style instead `std::size_t{32}` to avoid potential accidental conversions.
C++ is getting more and more ridiculous. I loved that language, and now I'm beginning to at the same time hate it and find it silly. It literally is like putting lipstick on a pig. Why uz? In what way does that indicate the type? Couldn't they (the "geniuses" from committee) come up with something approaching normal? Like u32, us, u64 etc? Really, uz, what on hell does that suggests?
You can't love c++. You tolerate just enough it to get things done.
On a related note WG21 clowns did not add ssize member methods to containers... only std::ssize, typical C++ nonsense
i am a fan of AAA, but auto index = 0uz is not very good readable.
u read it and think "wtf was that?" auto delay = 1us is understandable.
How about just not use "auto".....
2 letters for the more used unsigned size_t type, 1 letter for the less used signed size_t type. this is garbage
Every unsigned literal has a u in it, though. Having z behave differently would be weird and inconsistent (especially as there is no literal suffix for signed)