isocpp / isocpp/CppCoreGuidelines
P.5: static_assert(sizeof(Int) >= 4) assumes CHAR_BIT = 8, unlike the code it replaces
Nobody has claimed this yet.
- Dominant language
- CSS
- Stars
- 45.3k
- Forks
- 5.6k
- PR merge metrics
- No merged PRs in 30d
Description
P.5: Prefer compile-time checking to run-time checking has a loop that tries to find the bit width of a signed integer but suffers from signed-overflow UB.
The suggested replacement static_assert(sizeof(Int) >= 4) assumes that bit-width = sizeof(T) * 8. This is not true on some word-addressable DSPs, for example, where sizeof(int) = sizeof(char), and CHAR_BIT is 24 or 32. This would give a false-positive compile-time error which is less bad than letting code compile when it won't work. (CHAR_BIT is required to be at least 8).
static_assert(std::numeric_limits<Int>::digits >= 31) would be correct, I think. Integer types are guaranteed to have radix = 2. digits excludes the sign bit, but the runtime loop was probably assuming 2's or 1's complement (not sign/magnitude) and expecting to count it, too.
sizeof(Int) * CHAR_BIT >= 32 is shorter to type, and I was able to write it without having to check the numeric_limits docs to see which member was the bit-width of integer types. But that's might just be me. And now that I think about it, it's not as portable.
sizeof(Int) * CHAR_BIT assumes there are no padding bits. Any check inferring the number of value bits from the amount of storage isn't safe in general on a DeathStation 9000.
Of course all this complexity about what / how to check starts to make this a less-than-ideal example. A runtime check for endianness or 1's vs. 2's complement (maybe based on ~0) might work better, and use numeric_limits<T>::min() and max() to check for 1's vs. 2's complement. e.g. min+max == -1 means 2's complement. For signed types that won't overflow. For unsigned types we might have a false positive with max() == 0xFFFF... and -1 converted to unsigned gives 0xFFFF...
So I don't have a specific suggestion to replace both examples, but if you think std::numeric_limits<Int>::digits >= 31 will be distracting (e.g. why 31 instead of 32?) then it's worth considering a rewrite.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in the P.5 section of CppCoreGuidelines.md, where the signed-integer bit-width loop and its suggested static_assert replacement are described. Review the portability concerns around CHAR_BIT, padding bits, numeric_limits, and signed representations. Done means updating the example or explanatory text with a technically sound, clear approach; the issue does not prescribe one replacement.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- documentation
- Issue type
- Documentation
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100