-
Notifications
You must be signed in to change notification settings - Fork 8.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Various improvements for til::hash/point/size/rect #13093
Conversation
template<class T, std::enable_if_t<!details::is_span<T>::value, int> = 0> | ||
constexpr auto at(T& cont, const size_t i) -> decltype(cont[cont.size()]) | ||
template<typename T, typename I> | ||
constexpr auto at(T&& cont, const I i) noexcept -> decltype(auto) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
C++20?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Surprisingly C++14. Using auto
for parameter types is C++20 though...
template<class T, std::enable_if_t<!details::is_span<T>::value, int> = 0> | ||
constexpr auto at(T& cont, const size_t i) -> decltype(cont[cont.size()]) | ||
template<typename T, typename I> | ||
constexpr auto at(T&& cont, const I i) noexcept -> decltype(auto) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright so decltype(auto)
here (instead of auto
) makes sure that this can return an Elem&
(and will not return an Elem
instead)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep! We could also write constexpr decltype(auto) ...
but trailing types are technically cooler. 😅
POINT* as_win32_point() noexcept | ||
{ | ||
#pragma warning(suppress : 26490) // Don't use reinterpret_cast (type.1). | ||
return std::launder(reinterpret_cast<POINT*>(this)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
first time i have ever seen somebody introduce a launder
in the wild. Now, can you explain why it is necessary here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding is:
C++ has reinterpret_cast
but it's pretty much entirely useless.
You want to make an unsafe cast, because you know that the bitwise representation between both types is identical? Great. Because you can't. The language standard doesn't allow this and converting a til::point
to POINT
via reinterpret_cast
is invalid no matter what.
std::launder
is the next best tool in the language to say "I want what I want" even if it's purpose might not be for this. The spec says given std::launder(p)
: "All bytes of storage that would be reachable through the result are reachable through p". That's something I want: When you use that laundered pointer and make changes, I want those changes to be reachable through this
as well. But my hope is not to be correct, but rather to not find any surprises. Under MSVC it shouldn't be much of an issue though, as this compiler doesn't handle strict aliasing at all.
return std::launder(reinterpret_cast<RECT*>(this)); | ||
} | ||
|
||
// til::rect and POINT[2] have the exact same layout at the time of writing, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
now this is horrifying.
can you static_assert that they have the same layout somehow
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I have!
Co-authored-by: Dustin L. Howett <[email protected]>
Hello @lhecker! Because this pull request has the p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (
|
@@ -5,10 +5,20 @@ | |||
|
|||
namespace til | |||
{ | |||
// bit_cast is a backport of the STL's std::bit_cast to C++17. | |||
template<class To, class From, std::enable_if_t<std::conjunction_v<std::bool_constant<sizeof(To) == sizeof(From)>, std::is_trivially_copyable<To>, std::is_trivially_copyable<From>>, int> = 0> | |||
[[nodiscard]] constexpr To bit_cast(const From& _Val) noexcept | |||
{ | |||
// TODO: Replace til::bit_cast and __builtin_bit_cast with std::bit_cast |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(unrelated) oh man, there's a bare TODO here haha.
This commit includes various minor improvements to til::hash/point/size/rect
which accumulated while working on #4015.
size_t
indices intil::at
.til::as_unsigned
can be used to reinterpret a potentially signed integeras a unsigned one. This can potentially enable some optimizations as no sign
extension is needed anymore.
til::hash
can make use of this to drop about20% of the hashing of signed integers <= 32 bit. On x86 this translates to
a
mov
(virtually no latency) or no instructions at all, instead ofrequiring a
movsx
(some latency) for sign extension.til::point
operators that prefer mutability.This is a opinionated change, but it follows the STL style beter and
generates less assembly.
rect
scale_up/down andsize
divide_ceil.scale_up
will not depend on the operator header anymore.scale_down
/divide_ceil
can be implemented without checked numerics,so I did. It also follows the related GdiEngine code better now, which
makes me confident that we can replace GdiEngine's code with this.
They were only used in DxEngine and confusing as they weren't commutative.
Adding and then subtracting a size from a rect (and vice versa) didn't do
what you'd intuitively think it'd do. The code was replaced with addition
and clamps in DxEngine.
as_
casts for point/size/rect.This will aid the migration in Rectangle, Point, and Size need concerted structure #4015.
Validation Steps Performed
DxEngine
✅