mirror of
https://github.com/pocoproject/poco.git
synced 2025-04-16 15:01:15 +02:00
enh(Nullable, Optional): reimplement using std::optional (#4502)
This commit is contained in:
parent
03c35cff93
commit
e55bb7032d
@ -45,7 +45,7 @@ class Transcoder;
|
|||||||
namespace Keywords {
|
namespace Keywords {
|
||||||
|
|
||||||
|
|
||||||
static const NullData null = NULL_GENERIC;
|
static const NullData null = std::nullopt;
|
||||||
|
|
||||||
|
|
||||||
} // namespace Keywords
|
} // namespace Keywords
|
||||||
|
@ -20,18 +20,13 @@
|
|||||||
|
|
||||||
#include "Poco/Foundation.h"
|
#include "Poco/Foundation.h"
|
||||||
#include "Poco/Exception.h"
|
#include "Poco/Exception.h"
|
||||||
#include <algorithm>
|
#include <optional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
namespace Poco {
|
namespace Poco {
|
||||||
|
|
||||||
|
using NullType = std::nullopt_t;
|
||||||
enum NullType
|
|
||||||
{
|
|
||||||
NULL_GENERIC = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template <typename C>
|
template <typename C>
|
||||||
class Nullable
|
class Nullable
|
||||||
@ -58,88 +53,70 @@ class Nullable
|
|||||||
/// default construction.
|
/// default construction.
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Nullable():
|
Nullable()
|
||||||
/// Creates an empty Nullable.
|
/// Creates an empty Nullable.
|
||||||
_value(),
|
|
||||||
_isNull(true),
|
|
||||||
_null()
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Nullable(const NullType&):
|
Nullable(const NullType&)
|
||||||
/// Creates an empty Nullable.
|
/// Creates an empty Nullable.
|
||||||
_value(),
|
|
||||||
_isNull(true),
|
|
||||||
_null()
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Nullable(const C& value):
|
Nullable(const C& value):
|
||||||
/// Creates a Nullable with the given value.
|
/// Creates a Nullable with the given value.
|
||||||
_value(value),
|
_optional(value)
|
||||||
_isNull(false),
|
|
||||||
_null()
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Nullable(C&& value):
|
Nullable(C&& value):
|
||||||
/// Creates a Nullable by moving the given value.
|
/// Creates a Nullable by moving the given value.
|
||||||
_value(std::forward<C>(value)),
|
_optional(std::forward<C>(value))
|
||||||
_isNull(false),
|
|
||||||
_null()
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Nullable(const Nullable& other):
|
Nullable(const Nullable& other):
|
||||||
/// Creates a Nullable by copying another one.
|
/// Creates a Nullable by copying another one.
|
||||||
_value(other._value),
|
_optional(other._optional)
|
||||||
_isNull(other._isNull),
|
|
||||||
_null()
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Nullable(Nullable&& other) noexcept:
|
Nullable(Nullable&& other) noexcept:
|
||||||
/// Creates a Nullable by moving another one.
|
/// Creates a Nullable by moving another one.
|
||||||
_value(std::move(other._value)),
|
_optional(std::move(other._optional))
|
||||||
_isNull(other._isNull),
|
|
||||||
_null()
|
|
||||||
{
|
{
|
||||||
other._isNull = true;
|
other._optional.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
~Nullable()
|
~Nullable() = default;
|
||||||
/// Destroys the Nullable.
|
/// Destroys the Nullable.
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Nullable& assign(const C& value)
|
Nullable& assign(const C& value)
|
||||||
/// Assigns a value to the Nullable.
|
/// Assigns a value to the Nullable.
|
||||||
{
|
{
|
||||||
_value = value;
|
_optional.emplace(value);
|
||||||
_isNull = false;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Nullable& assign(C&& value)
|
Nullable& assign(C&& value)
|
||||||
/// Assigns a value to the Nullable.
|
/// Assigns a value to the Nullable.
|
||||||
{
|
{
|
||||||
_value = std::move(value);
|
_optional.emplace(std::move(value));
|
||||||
_isNull = false;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Nullable& assign(const Nullable& other)
|
Nullable& assign(const Nullable& other)
|
||||||
/// Assigns another Nullable.
|
/// Assigns another Nullable.
|
||||||
{
|
{
|
||||||
Nullable tmp(other);
|
if (&other != this)
|
||||||
swap(tmp);
|
_optional = other._optional;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Nullable& assign(NullType)
|
Nullable& assign(NullType)
|
||||||
/// Sets value to null.
|
/// Sets value to null.
|
||||||
{
|
{
|
||||||
_isNull = true;
|
_optional.reset();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,42 +141,39 @@ public:
|
|||||||
Nullable& operator = (Nullable&& other) noexcept
|
Nullable& operator = (Nullable&& other) noexcept
|
||||||
/// Moves another Nullable.
|
/// Moves another Nullable.
|
||||||
{
|
{
|
||||||
_isNull = other._isNull;
|
_optional = std::move(other._optional);
|
||||||
_value = std::move(other._value);
|
|
||||||
other._isNull = true;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Nullable& operator = (NullType)
|
Nullable& operator = (NullType)
|
||||||
/// Assigns another Nullable.
|
/// Assigns NullType.
|
||||||
{
|
{
|
||||||
_isNull = true;
|
_optional.reset();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap(Nullable& other) noexcept
|
void swap(Nullable& other) noexcept
|
||||||
/// Swaps this Nullable with other.
|
/// Swaps this Nullable with other.
|
||||||
{
|
{
|
||||||
std::swap(_value, other._value);
|
std::swap(_optional, other._optional);
|
||||||
std::swap(_isNull, other._isNull);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator == (const Nullable<C>& other) const
|
bool operator == (const Nullable<C>& other) const
|
||||||
/// Compares two Nullables for equality
|
/// Compares two Nullables for equality
|
||||||
{
|
{
|
||||||
return (_isNull && other._isNull) || (_isNull == other._isNull && _value == other._value);
|
return _optional == other._optional;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator == (const C& value) const
|
bool operator == (const C& value) const
|
||||||
/// Compares Nullable with value for equality
|
/// Compares Nullable with value for equality
|
||||||
{
|
{
|
||||||
return (!_isNull && _value == value);
|
return (_optional.has_value() && _optional.value() == value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator == (const NullType&) const
|
bool operator == (const NullType&) const
|
||||||
/// Compares Nullable with NullData for equality
|
/// Compares Nullable with NullData for equality
|
||||||
{
|
{
|
||||||
return _isNull;
|
return !_optional.has_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator != (const C& value) const
|
bool operator != (const C& value) const
|
||||||
@ -217,7 +191,7 @@ public:
|
|||||||
bool operator != (const NullType&) const
|
bool operator != (const NullType&) const
|
||||||
/// Compares with NullData for non equality
|
/// Compares with NullData for non equality
|
||||||
{
|
{
|
||||||
return !_isNull;
|
return _optional.has_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator < (const Nullable<C>& other) const
|
bool operator < (const Nullable<C>& other) const
|
||||||
@ -225,14 +199,7 @@ public:
|
|||||||
/// value is smaler than the other object's value.
|
/// value is smaler than the other object's value.
|
||||||
/// Null value is smaller than a non-null value.
|
/// Null value is smaller than a non-null value.
|
||||||
{
|
{
|
||||||
if (_isNull && other._isNull) return false;
|
return _optional < other._optional;
|
||||||
|
|
||||||
if (!_isNull && !other._isNull)
|
|
||||||
return (_value < other._value);
|
|
||||||
|
|
||||||
if (_isNull && !other._isNull) return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator > (const Nullable<C>& other) const
|
bool operator > (const Nullable<C>& other) const
|
||||||
@ -248,8 +215,8 @@ public:
|
|||||||
///
|
///
|
||||||
/// Throws a NullValueException if the Nullable is empty.
|
/// Throws a NullValueException if the Nullable is empty.
|
||||||
{
|
{
|
||||||
if (!_isNull)
|
if (_optional.has_value())
|
||||||
return _value;
|
return _optional.value();
|
||||||
else
|
else
|
||||||
throw NullValueException();
|
throw NullValueException();
|
||||||
}
|
}
|
||||||
@ -259,8 +226,8 @@ public:
|
|||||||
///
|
///
|
||||||
/// Throws a NullValueException if the Nullable is empty.
|
/// Throws a NullValueException if the Nullable is empty.
|
||||||
{
|
{
|
||||||
if (!_isNull)
|
if (_optional.has_value())
|
||||||
return _value;
|
return _optional.value();
|
||||||
else
|
else
|
||||||
throw NullValueException();
|
throw NullValueException();
|
||||||
}
|
}
|
||||||
@ -269,7 +236,10 @@ public:
|
|||||||
/// Returns the Nullable's value, or the
|
/// Returns the Nullable's value, or the
|
||||||
/// given default value if the Nullable is empty.
|
/// given default value if the Nullable is empty.
|
||||||
{
|
{
|
||||||
return _isNull ? deflt : _value;
|
if (_optional.has_value())
|
||||||
|
return _optional.value();
|
||||||
|
|
||||||
|
return deflt;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator C& ()
|
operator C& ()
|
||||||
@ -284,7 +254,7 @@ public:
|
|||||||
return value();
|
return value();
|
||||||
}
|
}
|
||||||
|
|
||||||
operator NullType& ()
|
operator const NullType& () const
|
||||||
/// Get reference to the value
|
/// Get reference to the value
|
||||||
{
|
{
|
||||||
return _null;
|
return _null;
|
||||||
@ -293,19 +263,18 @@ public:
|
|||||||
bool isNull() const
|
bool isNull() const
|
||||||
/// Returns true if the Nullable is empty.
|
/// Returns true if the Nullable is empty.
|
||||||
{
|
{
|
||||||
return _isNull;
|
return !_optional.has_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
/// Clears the Nullable.
|
/// Clears the Nullable.
|
||||||
{
|
{
|
||||||
_isNull = true;
|
_optional.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
C _value;
|
std::optional<C> _optional;
|
||||||
bool _isNull;
|
static constexpr NullType _null {std::nullopt};
|
||||||
NullType _null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#include "Poco/Foundation.h"
|
#include "Poco/Foundation.h"
|
||||||
#include "Poco/Exception.h"
|
#include "Poco/Exception.h"
|
||||||
#include <algorithm>
|
#include <optional>
|
||||||
|
|
||||||
|
|
||||||
namespace Poco {
|
namespace Poco {
|
||||||
@ -53,40 +53,33 @@ class Optional
|
|||||||
/// nillable == true.
|
/// nillable == true.
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Optional():
|
Optional()
|
||||||
/// Creates an empty Optional.
|
/// Creates an empty Optional.
|
||||||
_value(),
|
|
||||||
_isSpecified(false)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional(const C& value):
|
Optional(const C& value):
|
||||||
/// Creates a Optional with the given value.
|
/// Creates a Optional with the given value.
|
||||||
_value(value),
|
_optional(value)
|
||||||
_isSpecified(true)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional(C&& value):
|
Optional(C&& value):
|
||||||
/// Creates a Optional by moving the given value.
|
/// Creates a Optional by moving the given value.
|
||||||
_value(std::forward<C>(value)),
|
_optional(std::forward<C>(value))
|
||||||
_isSpecified(true)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional(const Optional& other):
|
Optional(const Optional& other):
|
||||||
/// Creates a Optional by copying another one.
|
/// Creates a Optional by copying another one.
|
||||||
_value(other._value),
|
_optional(other._optional)
|
||||||
_isSpecified(other._isSpecified)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional(Optional&& other) noexcept:
|
Optional(Optional&& other) noexcept:
|
||||||
/// Creates a Optional by moving another one.
|
/// Creates a Optional by moving another one.
|
||||||
_value(std::move(other._value)),
|
_optional(std::move(other._optional))
|
||||||
_isSpecified(other._isSpecified)
|
|
||||||
{
|
{
|
||||||
other._isSpecified = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~Optional()
|
~Optional()
|
||||||
@ -97,16 +90,14 @@ public:
|
|||||||
Optional& assign(const C& value)
|
Optional& assign(const C& value)
|
||||||
/// Assigns a value to the Optional.
|
/// Assigns a value to the Optional.
|
||||||
{
|
{
|
||||||
_value = value;
|
_optional.emplace(value);
|
||||||
_isSpecified = true;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional& assign(C&& value)
|
Optional& assign(C&& value)
|
||||||
/// Moves a value into the Optional.
|
/// Moves a value into the Optional.
|
||||||
{
|
{
|
||||||
_value = std::move(value);
|
_optional.emplace(std::move(value));
|
||||||
_isSpecified = true;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,17 +126,14 @@ public:
|
|||||||
|
|
||||||
Optional& operator = (Optional&& other) noexcept
|
Optional& operator = (Optional&& other) noexcept
|
||||||
{
|
{
|
||||||
_value = std::move(other._value);
|
_optional = std::move(other._optional);
|
||||||
_isSpecified = other._isSpecified;
|
|
||||||
other._isSpecified = false;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap(Optional& other) noexcept
|
void swap(Optional& other) noexcept
|
||||||
{
|
{
|
||||||
using std::swap;
|
using std::swap;
|
||||||
swap(_value, other._value);
|
swap(_optional, other._optional);
|
||||||
swap(_isSpecified, other._isSpecified);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const C& value() const
|
const C& value() const
|
||||||
@ -153,10 +141,10 @@ public:
|
|||||||
///
|
///
|
||||||
/// Throws a Poco::NullValueException if the value has not been specified.
|
/// Throws a Poco::NullValueException if the value has not been specified.
|
||||||
{
|
{
|
||||||
if (_isSpecified)
|
if (_optional.has_value())
|
||||||
return _value;
|
return _optional.value();
|
||||||
else
|
|
||||||
throw Poco::NullValueException();
|
throw Poco::NullValueException();
|
||||||
}
|
}
|
||||||
|
|
||||||
const C& value(const C& deflt) const
|
const C& value(const C& deflt) const
|
||||||
@ -164,24 +152,27 @@ public:
|
|||||||
/// given default value if the Optional's
|
/// given default value if the Optional's
|
||||||
/// value has not been specified.
|
/// value has not been specified.
|
||||||
{
|
{
|
||||||
return _isSpecified ? _value : deflt;
|
if (_optional.has_value())
|
||||||
|
return _optional.value();
|
||||||
|
|
||||||
|
return deflt;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isSpecified() const
|
bool isSpecified() const
|
||||||
/// Returns true iff the Optional's value has been specified.
|
/// Returns true iff the Optional's value has been specified.
|
||||||
{
|
{
|
||||||
return _isSpecified;
|
return _optional.has_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
/// Clears the Optional.
|
/// Clears the Optional.
|
||||||
{
|
{
|
||||||
_isSpecified = false;
|
_optional.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
C _value;
|
|
||||||
bool _isSpecified;
|
std::optional<C> _optional;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
using Poco::Bugcheck;
|
using Poco::Bugcheck;
|
||||||
using Poco::Exception;
|
using Poco::Exception;
|
||||||
@ -966,7 +967,7 @@ void CoreTest::testNullable()
|
|||||||
|
|
||||||
assertTrue (i == 1);
|
assertTrue (i == 1);
|
||||||
assertTrue (f == 1.5);
|
assertTrue (f == 1.5);
|
||||||
assertTrue (s == "abc");
|
assertTrue (s == "abc"s);
|
||||||
|
|
||||||
i.clear();
|
i.clear();
|
||||||
f.clear();
|
f.clear();
|
||||||
@ -1035,7 +1036,7 @@ void CoreTest::testNullable()
|
|||||||
assertTrue (n2 != n1);
|
assertTrue (n2 != n1);
|
||||||
assertTrue (n1 > n2);
|
assertTrue (n1 > n2);
|
||||||
|
|
||||||
NullType nd{};
|
const auto nd {std::nullopt};
|
||||||
assertTrue (n1 != nd);
|
assertTrue (n1 != nd);
|
||||||
assertTrue (nd != n1);
|
assertTrue (nd != n1);
|
||||||
n1.clear();
|
n1.clear();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user