-
Notifications
You must be signed in to change notification settings - Fork 564
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
Chore: Centralize Strong<> type unwrapping #4170
Chore: Centralize Strong<> type unwrapping #4170
Conversation
src/lib/utils/loadstor.h
Outdated
template <unsigned_integralish T> | ||
using wrapped_type = decltype([] { | ||
if constexpr(std::is_enum_v<T>) { | ||
return std::underlying_type_t<T>{}; | ||
} else { | ||
return Botan::strong_type_wrapped_type<T>{}; | ||
} | ||
}()); | ||
|
||
template <unsigned_integralish InT> | ||
constexpr auto unwrap_strong_type_or_enum(InT t) { | ||
if constexpr(std::is_enum_v<InT>) { | ||
// TODO: C++23: use std::to_underlying(in) instead | ||
return static_cast<std::underlying_type_t<InT>>(t); | ||
} else { | ||
return Botan::unwrap_strong_type(t); | ||
} | ||
} | ||
|
||
template <unsigned_integralish OutT, std::unsigned_integral T> | ||
constexpr auto wrap_strong_type_or_enum(T t) { | ||
if constexpr(std::is_enum_v<OutT>) { | ||
return static_cast<OutT>(t); | ||
} else { | ||
return Botan::wrap_strong_type<OutT>(t); | ||
} | ||
} |
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.
This is an extra layer of abstraction to make load/store
work with integer-enums as well. I feel that this would be useful for the other usage locations as well, so in theory we could also promote that into the implementation in strong_type.h
. As a result, the checked_cast_to
would then automagically work with enums as well.
a6b9ed7
to
2addfcf
Compare
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.
LGTM. I admit I mostly looked into the tests to see if every case was covered 😝
The only thing I can think of otherwise is support for strong types of strong types. In this case, loadstore does not accept these strong-ception types. But I don't think we want to support this anyway.
Yeah, I did wonder about that. But rejected the idea of strong type-ception as useless. Perhaps we should even statically check that in the strong type implementation. |
Bumping this to 3.6, with just 2 days until 3.5.0 release I'd rather not change anything except where we must. |
2addfcf
to
0f465bd
Compare
constexpr T& get() & { return m_value; } | ||
|
||
const T& get() const { return m_value; } | ||
constexpr const T& get() const& { return m_value; } | ||
|
||
constexpr T&& get() && { return std::move(m_value); } | ||
|
||
constexpr const T&& get() const&& { return std::move(m_value); } |
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.
This was inspired by #4175 (comment) and it simplifies the code of strong_type_unwrap()
significantly. In a sense, that it can now rely on overloading instead of explicitly std::move()
ing based on the type of object passed in.
... introduced in randombit#4170
... introduced in randombit#4170
... introduced in randombit#4170
... introduced in randombit#4170
Closes #4029.
This introduces
wrap_strong_type<>
andunwrap_strong_type()
that opportunistically wrap a given object into a strong type or extract the value from a strong type. It is meant to be used in generic contexts where we may or may not have to deal with a strong type. Examples are theload/store
methods andchecked_cast_to
.Another new helper is
strong_type_wrapped_type<>
. Given a potentially strong-typed type, this figures out the underlying type. That is quite useful to build generic functions that take both a bare value or a strong-type of the bare value. Like so:Many other generic locations that currently use byte-buffer-ish strong types don't have to rely on this, as those strong types masquerade as byte buffers and can be used directly. This is mostly targeting int-based strong types where we really need access to the underlying object for low-level operations.
We may or may not add this to 3.5.0 as it is a low-level refactoring. I'm quite confident in the CI coverage of this, though.