mirror of
https://github.com/pocoproject/poco.git
synced 2024-12-15 11:30:59 +01:00
Nullable for types without default constructor #617
This commit is contained in:
parent
b0fd3db526
commit
896c1ad016
@ -36,7 +36,7 @@ enum NullType
|
||||
template <typename C>
|
||||
class Nullable
|
||||
/// Nullable is a simple wrapper class for value types
|
||||
/// that allows objects or native type variables
|
||||
/// that allows objects or native type variables
|
||||
/// to have "null" value.
|
||||
///
|
||||
/// The class is useful for passing parameters to functions
|
||||
@ -60,34 +60,34 @@ class Nullable
|
||||
public:
|
||||
Nullable():
|
||||
/// Creates an empty Nullable.
|
||||
_value(),
|
||||
_isNull(true),
|
||||
_null()
|
||||
{
|
||||
std::memset(_value, 0, sizeof(C));
|
||||
}
|
||||
|
||||
Nullable(const NullType&):
|
||||
/// Creates an empty Nullable.
|
||||
_value(),
|
||||
_isNull(true),
|
||||
_null()
|
||||
{
|
||||
std::memset(_value, 0, sizeof(C));
|
||||
}
|
||||
|
||||
Nullable(const C& value):
|
||||
/// Creates a Nullable with the given value.
|
||||
_value(value),
|
||||
_isNull(false),
|
||||
_null()
|
||||
{
|
||||
new(_value) C(value);
|
||||
}
|
||||
|
||||
Nullable(const Nullable& other):
|
||||
/// Creates a Nullable by copying another one.
|
||||
_value(other._value),
|
||||
_isNull(other._isNull),
|
||||
_null()
|
||||
{
|
||||
new(_value) C(other.value());
|
||||
}
|
||||
|
||||
~Nullable()
|
||||
@ -98,7 +98,7 @@ public:
|
||||
Nullable& assign(const C& value)
|
||||
/// Assigns a value to the Nullable.
|
||||
{
|
||||
_value = value;
|
||||
new (_value) C(value);
|
||||
_isNull = false;
|
||||
return *this;
|
||||
}
|
||||
@ -140,20 +140,23 @@ public:
|
||||
void swap(Nullable& other)
|
||||
/// Swaps this Nullable with other.
|
||||
{
|
||||
std::swap(_value, other._value);
|
||||
char tmp[sizeof(C)];
|
||||
std::memcpy(tmp, _value, sizeof(C));
|
||||
std::memcpy(_value, other._value, sizeof(C));
|
||||
std::memcpy(other._value, tmp, sizeof(C));
|
||||
std::swap(_isNull, other._isNull);
|
||||
}
|
||||
|
||||
bool operator == (const Nullable<C>& other) const
|
||||
/// Compares two Nullables for equality
|
||||
{
|
||||
return (_isNull && other._isNull) || (_isNull == other._isNull && _value == other._value);
|
||||
return (_isNull && other._isNull) || (_isNull == other._isNull && value() == other.value());
|
||||
}
|
||||
|
||||
bool operator == (const C& value) const
|
||||
bool operator == (const C& val) const
|
||||
/// Compares Nullable with value for equality
|
||||
{
|
||||
return (!_isNull && _value == value);
|
||||
return (!_isNull && value() == val);
|
||||
}
|
||||
|
||||
bool operator == (const NullType&) const
|
||||
@ -162,10 +165,10 @@ public:
|
||||
return _isNull;
|
||||
}
|
||||
|
||||
bool operator != (const C& value) const
|
||||
bool operator != (const C& val) const
|
||||
/// Compares Nullable with value for non equality
|
||||
{
|
||||
return !(*this == value);
|
||||
return !(*this == val);
|
||||
}
|
||||
|
||||
bool operator != (const Nullable<C>& other) const
|
||||
@ -188,7 +191,7 @@ public:
|
||||
if (_isNull && other._isNull) return false;
|
||||
|
||||
if (!_isNull && !other._isNull)
|
||||
return (_value < other._value);
|
||||
return (value() < other.value());
|
||||
|
||||
if (_isNull && !other._isNull) return true;
|
||||
|
||||
@ -209,7 +212,7 @@ public:
|
||||
/// Throws a NullValueException if the Nullable is empty.
|
||||
{
|
||||
if (!_isNull)
|
||||
return _value;
|
||||
return *reinterpret_cast<C*>(_value);
|
||||
else
|
||||
throw NullValueException();
|
||||
}
|
||||
@ -220,7 +223,7 @@ public:
|
||||
/// Throws a NullValueException if the Nullable is empty.
|
||||
{
|
||||
if (!_isNull)
|
||||
return _value;
|
||||
return *reinterpret_cast<const C*>(_value);
|
||||
else
|
||||
throw NullValueException();
|
||||
}
|
||||
@ -229,7 +232,7 @@ public:
|
||||
/// Returns the Nullable's value, or the
|
||||
/// given default value if the Nullable is empty.
|
||||
{
|
||||
return _isNull ? deflt : _value;
|
||||
return _isNull ? deflt : *reinterpret_cast<const C*>(_value);
|
||||
}
|
||||
|
||||
operator C& ()
|
||||
@ -256,7 +259,7 @@ public:
|
||||
{
|
||||
return _isNull;
|
||||
}
|
||||
|
||||
|
||||
void clear()
|
||||
/// Clears the Nullable.
|
||||
{
|
||||
@ -264,7 +267,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
C _value;
|
||||
char _value[sizeof(C)];
|
||||
bool _isNull;
|
||||
NullType _null;
|
||||
};
|
||||
|
@ -360,8 +360,42 @@ void CoreTest::testAtomicCounter()
|
||||
}
|
||||
|
||||
|
||||
class NonDefaultConstructible
|
||||
{
|
||||
public:
|
||||
NonDefaultConstructible(int val): _val(val)
|
||||
{
|
||||
}
|
||||
|
||||
NonDefaultConstructible operator=(int val)
|
||||
{
|
||||
_val = val;
|
||||
}
|
||||
|
||||
bool operator == (const NonDefaultConstructible& other) const
|
||||
{
|
||||
return (_val == other._val);
|
||||
}
|
||||
|
||||
int value() const
|
||||
{
|
||||
return _val;
|
||||
}
|
||||
|
||||
private:
|
||||
NonDefaultConstructible();
|
||||
int _val;
|
||||
};
|
||||
|
||||
|
||||
void CoreTest::testNullable()
|
||||
{
|
||||
Nullable<NonDefaultConstructible> ndc;
|
||||
assert (ndc.isNull());
|
||||
ndc = 42;
|
||||
assert (!ndc.isNull());
|
||||
assert (ndc.value() == 42);
|
||||
|
||||
Nullable<int> i;
|
||||
Nullable<double> f;
|
||||
Nullable<std::string> s;
|
||||
|
Loading…
Reference in New Issue
Block a user