Added opaque_handle::ptr_cast(): Use `try_cast()` for complete types, and `unsafe_cast()` for incomplete types. This is used *only* for `operator [const] T*()`, since this is intended for C interop. `operator->` and `operator*` will only work with complete types, as they should.

Fortune for opaque_handle's current commit: Curse − 凶
master
Avril 3 years ago
parent 7d55dcf124
commit 8168dd904d
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -100,6 +100,19 @@ struct opaque_handle final {
template<typename T> template<typename T>
constexpr T* try_cast() noexcept { return _impl ? _impl->try_cast<T>() : nullptr; } constexpr T* try_cast() noexcept { return _impl ? _impl->try_cast<T>() : nullptr; }
/// ptr_cast(): use try_cast() for complete types, and unsafe_cast() for incomplete types.
template<typename T>
constexpr T* ptr_cast() noexcept {
if constexpr(opaque_is_incomplete<T>) return unsafe_cast<T>();
else return try_cast<T>();
}
template<typename T>
constexpr const T* ptr_cast() const noexcept {
if constexpr(opaque_is_incomplete<T>) return unsafe_cast<T>();
else return try_cast<T>();
}
template<typename T, cast_kind Kind = CAST_SAFE> template<typename T, cast_kind Kind = CAST_SAFE>
inline const T& cast() const { inline const T& cast() const {
if constexpr(Kind >= CAST_UNSAFE) if constexpr(Kind >= CAST_UNSAFE)
@ -118,6 +131,8 @@ struct opaque_handle final {
constexpr bool has_value() const noexcept { return bool(_impl); } constexpr bool has_value() const noexcept { return bool(_impl); }
constexpr explicit operator bool() const noexcept { return has_value(); } constexpr explicit operator bool() const noexcept { return has_value(); }
// XXX: NOTE: operator-> and operator* do not, and SHOULD NOT, work for incomplete types. only `ptr_cast()` and `operator [const] T*()` should consider the completeness of the type.
//TODO: Test these, we may need to do the same thing we did for `operator*`, but with a shim that has `operator T*` and `operator->` instead of `operator T&`. //TODO: Test these, we may need to do the same thing we did for `operator*`, but with a shim that has `operator T*` and `operator->` instead of `operator T&`.
template<typename T> template<typename T>
constexpr const T* operator->() const noexcept(std::is_void_v<T>) { constexpr const T* operator->() const noexcept(std::is_void_v<T>) {
@ -147,13 +162,11 @@ struct opaque_handle final {
*/ */
template<typename T> template<typename T>
constexpr operator T*() noexcept { constexpr operator T*() noexcept {
if constexpr(opaque_is_incomplete<T>) return unsafe_cast<T>(); return ptr_cast<T>();
else return try_cast<T>();
} }
template<typename T> template<typename T>
constexpr operator const T*() const noexcept { constexpr operator const T*() const noexcept {
if constexpr(opaque_is_incomplete<T>) return unsafe_cast<T>(); return ptr_cast<T>();
else return try_cast<T>();
} }
private: private:

Loading…
Cancel
Save