diff options
-rw-r--r-- | keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h | 59 |
1 files changed, 35 insertions, 24 deletions
diff --git a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h index 97dab68217..cb29c64b1e 100644 --- a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h +++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h @@ -280,39 +280,50 @@ inline KeyParameter Authorization(TypedTag<tag_type, tag> ttag, Args&&... args) */ template <typename ValueT> class NullOr { - template <typename T> - struct reference_initializer { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wnull-dereference" - static T&& init() { return *static_cast<std::remove_reference_t<T>*>(nullptr); } -#pragma GCC diagnostic pop - }; - template <typename T> + using internal_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value, + std::remove_reference_t<ValueT>*, ValueT>; + struct pointer_initializer { - static T init() { return nullptr; } + static std::nullptr_t init() { return nullptr; } }; - template <typename T> struct value_initializer { - static T init() { return T(); } + static ValueT init() { return ValueT(); } }; + struct value_pointer_deref_t { + static ValueT& deref(ValueT& v) { return v; } + }; + struct reference_deref_t { + static auto& deref(internal_t v) { return *v; } + }; + using initializer_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value || + std::is_pointer<ValueT>::value, + pointer_initializer, value_initializer>; + using deref_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value, reference_deref_t, + value_pointer_deref_t>; + + public: + NullOr() : value_(initializer_t::init()), null_(true) {} template <typename T> - using initializer_t = - std::conditional_t<std::is_lvalue_reference<T>::value, reference_initializer<T>, - std::conditional_t<std::is_pointer<T>::value, pointer_initializer<T>, - value_initializer<T>>>; - - public: - NullOr() : value_(initializer_t<ValueT>::init()), null_(true) {} - NullOr(ValueT&& value) : value_(std::forward<ValueT>(value)), null_(false) {} + NullOr(T&& value, typename std::enable_if< + !std::is_lvalue_reference<ValueT>::value && + std::is_same<std::decay_t<ValueT>, std::decay_t<T>>::value, + int>::type = 0) + : value_(std::forward<ValueT>(value)), null_(false) {} + template <typename T> + NullOr(T& value, typename std::enable_if< + std::is_lvalue_reference<ValueT>::value && + std::is_same<std::decay_t<ValueT>, std::decay_t<T>>::value, + int>::type = 0) + : value_(&value), null_(false) {} bool isOk() const { return !null_; } - const ValueT& value() const & { return value_; } - ValueT& value() & { return value_; } - ValueT&& value() && { return std::move(value_); } + const ValueT& value() const& { return deref_t::deref(value_); } + ValueT& value() & { return deref_t::deref(value_); } + ValueT&& value() && { return std::move(deref_t::deref(value_)); } - private: - ValueT value_; + private: + internal_t value_; bool null_; }; |