--
You received this message because you are subscribed to the Google Groups "cxx" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cxx+uns...@chromium.org.
To view this discussion visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CACWgwAZ7UKKCkfX7Pqcqj7jsN%2BrzVkRhid-eZp7jFefjfy2ViA%40mail.gmail.com.
To view this discussion visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CACWgwAYYyyVhGTncgDr4ZEYkfDrZ6m4cFsCOHT2Pq9VBXEWGUg%40mail.gmail.com.
To view this discussion visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CAKFU2SC84EpV4FE70sZCawj%2BwB2fRmwb3D04XvuGZRewj09CFQ%40mail.gmail.com.
Do you have examples for situations where negative ByteCounts are needed? From a distance, having something called ByteCount be negative seems quite surprising to me.
To view this discussion visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CAOXvDB2BDSWZM6ToH_6OkZb6Fi44KKXZ_9CW1DmVONzvffuqmw%40mail.gmail.com.
The use of a signed integer for base::ByteCount was inspired from the use of a signed integer for base::TimeDelta.Comparing the 2 choices:signed+ Subtracting [large value] from [small value] works.+ Can represent a possibly negative byte delta [example]- Cannot represent values larger than 8EiB (my assumption is that this is rarely needed)unsigned- Subtracting [large value] from [small value] is an error.- Cannot represent a possibly negative byte delta [example]+ Can represent value larger than 8EiB
The use of a signed integer for base::ByteCount was inspired from the use of a signed integer for base::TimeDelta.Comparing the 2 choices:signed+ Subtracting [large value] from [small value] works.+ Can represent a possibly negative byte delta [example]- Cannot represent values larger than 8EiB (my assumption is that this is rarely needed)unsigned- Subtracting [large value] from [small value] is an error.- Cannot represent a possibly negative byte delta [example]+ Can represent value larger than 8EiB
On Thu, Aug 28, 2025 at 3:15 PM K. Moon <km...@chromium.org> wrote:
The use of a signed integer for base::ByteCount was inspired from the use of a signed integer for base::TimeDelta.
--
You received this message because you are subscribed to the Google Groups "cxx" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cxx+uns...@chromium.org.
On Fri, Aug 29, 2025 at 1:18 AM Leszek Swirski <les...@chromium.org> wrote:
Having signed types for diff and unsigned types for size has its own caveats, like how there would be cases of undefined subtraction between two valid sizes (like how ptrdiff_t can be UB for large enough pointer subtraction); unless ByteCount was constrained to the intersection of int64_t and uint64_t range, in which case it doesn't super matter which underlying representation it has: we either have dodgy code when it exits its valid range or it needs to anyway be runtime checked for exceeding its valid range.
Using CheckedNumeric under the hood would eliminate this problem, as it would automatically do the runtime check that the result is valid.It would also constrain the set of problem cases to O(1): the implementation of these types themselves. This is preferable to potentially having problems at the usage sites.PK
Having signed types for diff and unsigned types for size has its own caveats, like how there would be cases of undefined subtraction between two valid sizes (like how ptrdiff_t can be UB for large enough pointer subtraction); unless ByteCount was constrained to the intersection of int64_t and uint64_t range, in which case it doesn't super matter which underlying representation it has: we either have dodgy code when it exits its valid range or it needs to anyway be runtime checked for exceeding its valid range.
I decided not to have separate types for "absolute quantity" and "delta" when I implemented the API, because we cannot deduce the right type to use for the result of an operation without extra context:base::ByteCount total_ram;base::ByteCount used_ram;base::ByteCount available_ram = total_ram - used_ram; // we want the result of this subtraction to be a ByteSizebase::ByteCount previous_size;base::ByteCount new_size;base::ByteCount size_delta = new_size - previous_size; // we want the result of this subtraction to be a ByteSizeDeltabase::ByteCount bytes_transferred_at_beginning_of_interval;base::ByteCount bytes_transferred_at_end_of_interval;base::ByteCount bytes_transferred_during_interval; // depending on the larger context, we could argue that this is a ByteSize (absolute amount of bytes transferred during the interval) or a ByteSizeDelta (variation of the total amount of bytes transferred)
--
You received this message because you are subscribed to the Google Groups "cxx" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cxx+uns...@chromium.org.
Software Engineer
Google Germany GmbH
Erika-Mann-Straße 33 80636 München
Geschäftsführer: Paul Manicle, Liana Sebastian
Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg
Diese E-Mail ist vertraulich. Falls sie diese fälschlicherweise erhalten haben sollten, leiten Sie diese bitte nicht an jemand anderes weiter, löschen Sie alle Kopien und Anhänge davon und lassen Sie mich bitte wissen, dass die E-Mail an die falsche Person gesendet wurde. This e-mail is confidential. If you received this communication by mistake, please don't forward it to anyone else, please erase all copies and attachments, and please let me know that it has gone to the wrong person.
ByteCount, is because our existing codebase uses signed integers for "byte sizes" [examples: 1, 2, 3]. My assessment was that negative byte counts were more common than positive counts exceeding the max int64_t, so using int64_t would make the migration easier (no need to change logic as part of the migration). This assessment seems correct, as the migration to ByteCount has progressed without triggering CheckedNumeric failures [code]. To view this discussion visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CAGD3t5EmtL6e%2BKpkpbH8YADPKDTeTS1C9n2oQY70KgyfseaKUw%40mail.gmail.com.
(This is also similar to how point + vector2d is point, not vector2d. And yes, the delta may be negative; that's fine.)PKOn Wed, Oct 8, 2025, 9:13 AM Peter Kasting <zer...@gmail.com> wrote:ByteSize + ByteSizeDelta should be a ByteSize, not a ByteSizeDelta. Follow the example of the Time and TimeDelta operators.PK
ByteSizeDelta + ByteSize should be well-defined and equivalent to the other order. ByteSizeDelta - ByteSize, however, should not compile. Addition is commutative; subtraction is not. And this is coherent with how subtraction is equivalent to adding a negative: negating a ByteSize is nonsensical.IIRC this is how Time types work also.
To view this discussion visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CAJTZ7LL4wUZSWJ9PHyxi6iANOL-CNrkwUuLXFcN7jCMq-1fJeA%40mail.gmail.com.
Not to stir the pot, but I disagree on this point:"For instance, TotalPhysicalMemory - UsedPhysicalMemory = AvailablePhysicalMemory. All of these are ByteCounts which can be represented independently, not deltas, yet the math makes sense too."The computed value is a delta between two other values by definition. There is nothing about that expression that says that the second operand must be less than the first, so it's perfectly valid for the result to be negative. If, in this particular context, the expectation is that the result should always be positive and that it should be interpreted as a positive count rather than a delta, then that should be reflected in the code. For example:avail = base::saturated_cast<ByteCount>(total - used);or maybe even checked_cast<> if you want to crash in the unexpected case.It seems that I'm in the "counts and deltas are different things and they shouldn't be confused" camp. If we do consider them to be two distinct things, then I like my counts to be unsigned, thankyouverymuch. :-)
If we're talking about style guides, then don't forget this gem: "Use size_t for object and allocation sizes, object counts, array and pointer offsets, vector indices, and so on. This prevents casts when dealing with STL APIs, and if followed consistently across the codebase, minimizes casts elsewhere."
The chromium style guidance to use size_t is very much intentional, and long-standing. It also does not actually diverge from the upstream style guide; the upstream guide supports use of unsigned types when doing so avoids conversions, which is important in this case since basically all stdlib and many os functions take/return unsigned types (e.g. size_t, uint64_t, DWORD). I've discussed the style guidance a lot with Google style arbiters and I don't think we want to change direction.This is part of why I was so surprised that ByteCount uses a signed underlying type. I think this is problematic and potentially introduces more problems than the ByteCount type solves. I think fixing this is imperative, enough so that (as I already mentioned) I am willing to volunteer the eng time to fix it.I don't think a delta type is critical, but the thread consensus was to add one. I also don't think it's necessary to tell people to stop using ByteCount in the meantime, but Avi apparently did. In my view, we can Just Fix This without halting the world or inconveniencing any engineers.
To view this discussion visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CACwGi-4yO2-Loz4YQrq-_47_yFJFaGauU47-FHtqMJVbj8qjFg%40mail.gmail.com.
A lot of the research that I was putting into my conversions was figuring out how to move "int + -1 for unknown/error" into optional<ByteCount>. While we gain some by moving to (now) ByteSize, we gain so much more by retrofitting with optional<ByteSize> that I think that effort to detangle it will be worth doing.