4 ms·
> I'm still wondering why `(int)` is spelled `reinterpret_cast<int>` in C++ 1. because it is greppable and unsafe 2. because there is also static_cast and dyn
by germandiago 4y ago
> I'm still wondering why `(int)` is spelled `reinterpret_cast<int>` in C++
1. because it is greppable and unsafe
2. because there is also static_cast and dynamic_cast
3. Because in C (int) is all three at once and not greppable -> C will let you do whatever, C++ will not let you do with a static_cast everything you can do with a (T) cast.
All in all, it is nice to ask, but if you do not know what you are talking about except for the surface, then, you should not say:
> Do they just like hitting keys on the keyboard?
No, we do not, but we hate even more to get an ungreppable, undecipherable (semantically) casting lost somewhere in several tens of thousands of lines of code :) This eases finding the suspicious code more easily.
- wewtyflakes 4y agoIt doesn't matter since (int) is in the C++ language regardless of how we feel about it, so it seems their point still stands.
- robotresearcher 4y agoSeems to be found by grep fine: % echo 'int x = (int)1.2f;' > foo % grep '(int)' foo int x = (int)1.2f; Does greppable mean something else in this context?
- ghghgfdfgh 4y agoI'm assuming they didn't mean "grep" in a literal sense, rather that it is easier to find keywords like "reinterpret_cast" when scanning your eyes through code, whereas with C-style casts you'd have a much harder time.
- germandiago 4y agoYes I meant this. But grepping can also be a real problem.It is not just plain int what you cast.
- germandiago 4y agoNow find casts that are known to be as unsafe as reinterpret cast for the whole set of types your codebase deals with to audit a violation of the type system. What would you grep? I would grep 'reinterpret_cast' and I would set warning as error for the c-style casts. So you can assume my codebase does not have any. I will find any cast to reference, pointer, etc. for any type. How would you do tjat if you do: (int)a ((int)(MyType*)) and many, many more...
- robotresearcher 4y agoThat makes sense, thanks. Grepping for C syntax casts with arbitrary stuff between the parens is clearly not going to work.
- astrange 4y ago> 1. because it is greppable and unsafe But it is not unsafe, or rather, the C++ casts aren't more safe. They have the same semantics. There are differences casting between class types, but with numeric types the issues are how to handle the value not fitting in (or being imprecise) in the destination type. Casting a value to int in C++ that overflows is still UB. It doesn't fix C's other strange numeric issues either, like how `unsigned short` * `unsigned short` produces `int`.
- shaklee3 4y agothey are unsafe because if you try to cast something that's not valid the compiler won't let you. you can then choose to ignore it and be unsafe, or figure out the problem and fix it.
- astrange 4y agoYou can still cast INT_MAX to short no matter how you spell the cast, and the result won't be correct.
- germandiago 4y agoThere are more casts than those. Anda reinterpet cast is a superset of a static cast. If you want to narrow, you would use static cast, not reinterpret cast. If you want to reinterpret a set of bytes as another object then you reinterpret cast (actuall use std::bit_cast, will catch more errors,). So yes, you can still do that but consciously. In C you could even turn a cast that is essentially a static cast into a reinterpret cast by accident and the compiler would say nothing.
- astrange 4y ago> If you want to narrow, you would use static cast, not reinterpret cast. But if you do that, it's not safe! It's the same as C, which is not safe - it's "implementation defined". Swift would trap on overflow here.
- BenFrantzDale 4y agoA reinterpret_cast is something that shows up very rarely, so it’s fine that it’s not concise. And when it is used, it usually can do with a function naming it. I try to have a “no raw reinterpret_cast” view unless it’s chars to unsigned chars for string stuff. And as others have said, it’s grepable and can’t cast away constness. If I’m handing a const unsigned char* to a function taking a char* that I know wind modify the data, I don’t want that to be (char*)ptr. I want it to be const_cast<char*>(reinterpret_cast<const char*>(ptr)) because yikes, it should stand out because it’s awful. And then I’d wrap that godawful cast in a function overloading the legacy C interface, so the overload has one job: to encapsulate the logic that the legacy function isn’t const correct. So then I’d have like void wrappedFoo(std::string_view s) { foo(const_cast<char*>(reinterpret_cast<const char*>(s.data())), s.size()); } with lots of comments about the cast.