aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKitsune Ral <Kitsune-Ral@users.sf.net>2018-11-23 19:18:51 +0900
committerKitsune Ral <Kitsune-Ral@users.sf.net>2018-12-08 16:46:57 +0900
commited1f15151babee9ebc690ffa5c2593119540e8f0 (patch)
tree5b7d5de859a8b22525b87d065f9152055b7d9aa2
parentced7179117fd67cb1632f943f4ba1fde96423c0c (diff)
downloadlibquotient-ed1f15151babee9ebc690ffa5c2593119540e8f0.tar.gz
libquotient-ed1f15151babee9ebc690ffa5c2593119540e8f0.zip
Omittable: make operator-> and operator* return an empty object if omitted == true
That is, instead of Q_ASSERTing in debug builds (release builds already work that way). The idea is that since the value is default-initialised anyway it can be used as a "blank canvas" to access specific fields inside the value's structure. The next commit will use that.
-rw-r--r--lib/util.h26
1 files changed, 14 insertions, 12 deletions
diff --git a/lib/util.h b/lib/util.h
index 6b5c89e6..1028e059 100644
--- a/lib/util.h
+++ b/lib/util.h
@@ -88,17 +88,19 @@ namespace QMatrixClient
static_assert(!std::is_reference<T>::value,
"You cannot make an Omittable<> with a reference type");
public:
+ using value_type = std::decay_t<T>;
+
explicit Omittable() : Omittable(none) { }
- Omittable(NoneTag) : _value(std::decay_t<T>()), _omitted(true) { }
- Omittable(const std::decay_t<T>& val) : _value(val) { }
- Omittable(std::decay_t<T>&& val) : _value(std::move(val)) { }
- Omittable<T>& operator=(const std::decay_t<T>& val)
+ Omittable(NoneTag) : _value(value_type()), _omitted(true) { }
+ Omittable(const value_type& val) : _value(val) { }
+ Omittable(value_type&& val) : _value(std::move(val)) { }
+ Omittable<T>& operator=(const value_type& val)
{
_value = val;
_omitted = false;
return *this;
}
- Omittable<T>& operator=(std::decay_t<T>&& val)
+ Omittable<T>& operator=(value_type&& val)
{
_value = std::move(val);
_omitted = false;
@@ -106,15 +108,15 @@ namespace QMatrixClient
}
bool omitted() const { return _omitted; }
- const std::decay_t<T>& value() const { Q_ASSERT(!_omitted); return _value; }
- std::decay_t<T>& value() { Q_ASSERT(!_omitted); return _value; }
- std::decay_t<T>&& release() { _omitted = true; return std::move(_value); }
+ const value_type& value() const { Q_ASSERT(!_omitted); return _value; }
+ value_type& value() { Q_ASSERT(!_omitted); return _value; }
+ value_type&& release() { _omitted = true; return std::move(_value); }
operator bool() const { return !omitted(); }
- const std::decay<T>* operator->() const { return &value(); }
- std::decay_t<T>* operator->() { return &value(); }
- const std::decay_t<T>& operator*() const { return value(); }
- std::decay_t<T>& operator*() { return value(); }
+ const value_type* operator->() const { return &_value; }
+ value_type* operator->() { return &_value; }
+ const value_type& operator*() const { return _value; }
+ value_type& operator*() { return _value; }
private:
T _value;