mirror of
https://github.com/tfussell/xlnt.git
synced 2024-03-22 13:11:17 +08:00
Merge 45eadf567432c6220f689477b933fffe5b2294f8 into 297b331435d6dee09bf89c8a5ad974b01f18039b
This commit is contained in:
commit
cbc8bdca94
@ -27,6 +27,7 @@
|
|||||||
#include "xlnt/utils/numeric.hpp"
|
#include "xlnt/utils/numeric.hpp"
|
||||||
#include "xlnt/xlnt_config.hpp"
|
#include "xlnt/xlnt_config.hpp"
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
@ -74,28 +75,26 @@ public:
|
|||||||
/// Default contructor. is_set() will be false initially.
|
/// Default contructor. is_set() will be false initially.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
optional() noexcept
|
optional() noexcept
|
||||||
: has_value_(false)
|
: optional_ptr()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs this optional with a value.
|
/// Copy constructs this optional with a value.
|
||||||
/// noexcept if T copy ctor is noexcept
|
/// noexcept if T copy ctor is noexcept
|
||||||
/// </summary>
|
/// </summary>
|
||||||
optional(const T &value) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(ctor_copy_T_noexcept{}))
|
optional(const T &value) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(ctor_copy_T_noexcept{}))
|
||||||
: has_value_(true)
|
: optional_ptr(new T(value))
|
||||||
{
|
{
|
||||||
new (&storage_) T(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs this optional with a value.
|
/// Move constructs this optional with a value.
|
||||||
/// noexcept if T move ctor is noexcept
|
/// noexcept if T move ctor is noexcept
|
||||||
/// </summary>
|
/// </summary>
|
||||||
optional(T &&value) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(ctor_move_T_noexcept{}))
|
optional(T &&value) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(ctor_move_T_noexcept{}))
|
||||||
: has_value_(true)
|
: optional_ptr(new T(std::move(value)))
|
||||||
{
|
{
|
||||||
new (&storage_) T(std::move(value));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -103,12 +102,13 @@ public:
|
|||||||
/// noexcept if T copy ctor is noexcept
|
/// noexcept if T copy ctor is noexcept
|
||||||
/// </summary>
|
/// </summary>
|
||||||
optional(const optional &other) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(copy_ctor_noexcept{}))
|
optional(const optional &other) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(copy_ctor_noexcept{}))
|
||||||
: has_value_(other.has_value_)
|
|
||||||
{
|
{
|
||||||
if (has_value_)
|
if (other.optional_ptr != nullptr)
|
||||||
{
|
{
|
||||||
new (&storage_) T(other.value_ref());
|
optional_ptr = std::make_unique<T>(*other.optional_ptr);
|
||||||
}
|
} else {
|
||||||
|
optional_ptr = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -116,13 +116,8 @@ public:
|
|||||||
/// noexcept if T move ctor is noexcept
|
/// noexcept if T move ctor is noexcept
|
||||||
/// </summary>
|
/// </summary>
|
||||||
optional(optional &&other) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(move_ctor_noexcept{}))
|
optional(optional &&other) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(move_ctor_noexcept{}))
|
||||||
: has_value_(other.has_value_)
|
: optional_ptr(std::move(other.optional_ptr))
|
||||||
{
|
{
|
||||||
if (has_value_)
|
|
||||||
{
|
|
||||||
new (&storage_) T(std::move(other.value_ref()));
|
|
||||||
other.clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -131,14 +126,12 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
optional &operator=(const optional &other) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(set_copy_noexcept_t{} && clear_noexcept_t{}))
|
optional &operator=(const optional &other) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(set_copy_noexcept_t{} && clear_noexcept_t{}))
|
||||||
{
|
{
|
||||||
if (other.has_value_)
|
if (other.optional_ptr != nullptr)
|
||||||
{
|
{
|
||||||
set(other.value_ref());
|
optional_ptr.reset(new T(*other.optional_ptr));
|
||||||
}
|
} else {
|
||||||
else
|
optional_ptr = nullptr;
|
||||||
{
|
}
|
||||||
clear();
|
|
||||||
}
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,15 +141,7 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
optional &operator=(optional &&other) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(set_move_noexcept_t{} && clear_noexcept_t{}))
|
optional &operator=(optional &&other) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(set_move_noexcept_t{} && clear_noexcept_t{}))
|
||||||
{
|
{
|
||||||
if (other.has_value_)
|
optional_ptr = std::move(other.optional_ptr);
|
||||||
{
|
|
||||||
set(std::move(other.value_ref()));
|
|
||||||
other.clear();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,7 +150,7 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
~optional() noexcept // note:: unconditional because msvc freaks out otherwise
|
~optional() noexcept // note:: unconditional because msvc freaks out otherwise
|
||||||
{
|
{
|
||||||
clear();
|
optional_ptr.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -174,7 +159,7 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
bool is_set() const noexcept
|
bool is_set() const noexcept
|
||||||
{
|
{
|
||||||
return has_value_;
|
return (optional_ptr != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -182,49 +167,19 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
void set(const T &value) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(set_copy_noexcept_t{}))
|
void set(const T &value) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(set_copy_noexcept_t{}))
|
||||||
{
|
{
|
||||||
#if defined(__GNUC__) && !defined(__clang__)
|
optional_ptr.reset(new T(value));
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
|
||||||
#endif
|
|
||||||
if (has_value_)
|
|
||||||
{
|
|
||||||
value_ref() = value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
new (&storage_) T(value);
|
|
||||||
has_value_ = true;
|
|
||||||
}
|
|
||||||
#if defined(__GNUC__) && !defined(__clang__)
|
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Moves the value into the stored value
|
/// Moves the value into the stored value
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
// note seperate overload for two reasons (as opposed to perfect forwarding)
|
||||||
|
// 1. have to deal with implicit conversions internally with perfect forwarding
|
||||||
|
// 2. have to deal with the noexcept specfiers for all the different variations
|
||||||
|
// overload is just far and away the simpler solution
|
||||||
void set(T &&value) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(set_move_noexcept_t{}))
|
void set(T &&value) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(set_move_noexcept_t{}))
|
||||||
{
|
{
|
||||||
// note seperate overload for two reasons (as opposed to perfect forwarding)
|
optional_ptr.reset(new T(std::move(value)));
|
||||||
// 1. have to deal with implicit conversions internally with perfect forwarding
|
|
||||||
// 2. have to deal with the noexcept specfiers for all the different variations
|
|
||||||
// overload is just far and away the simpler solution
|
|
||||||
#if defined(__GNUC__) && !defined(__clang__)
|
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
|
||||||
#endif
|
|
||||||
if (has_value_)
|
|
||||||
{
|
|
||||||
value_ref() = std::move(value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
new (&storage_) T(std::move(value));
|
|
||||||
has_value_ = true;
|
|
||||||
}
|
|
||||||
#if defined(__GNUC__) && !defined(__clang__)
|
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -232,7 +187,7 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
optional &operator=(const T &rhs) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(set_copy_noexcept_t{}))
|
optional &operator=(const T &rhs) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(set_copy_noexcept_t{}))
|
||||||
{
|
{
|
||||||
set(rhs);
|
optional_ptr.reset(new T(rhs));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,7 +196,7 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
optional &operator=(T &&rhs) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(set_move_noexcept_t{}))
|
optional &operator=(T &&rhs) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(set_move_noexcept_t{}))
|
||||||
{
|
{
|
||||||
set(std::move(rhs));
|
optional_ptr.reset(new T(std::move(rhs)));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,11 +205,7 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
void clear() noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(clear_noexcept_t{}))
|
void clear() noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(clear_noexcept_t{}))
|
||||||
{
|
{
|
||||||
if (has_value_)
|
optional_ptr.reset();
|
||||||
{
|
|
||||||
reinterpret_cast<T *>(&storage_)->~T();
|
|
||||||
}
|
|
||||||
has_value_ = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -263,12 +214,11 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
T &get()
|
T &get()
|
||||||
{
|
{
|
||||||
if (!has_value_)
|
if (optional_ptr == nullptr)
|
||||||
{
|
{
|
||||||
throw invalid_attribute();
|
throw invalid_attribute();
|
||||||
}
|
}
|
||||||
|
return *optional_ptr;
|
||||||
return value_ref();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -277,12 +227,11 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
const T &get() const
|
const T &get() const
|
||||||
{
|
{
|
||||||
if (!has_value_)
|
if (optional_ptr == nullptr)
|
||||||
{
|
{
|
||||||
throw invalid_attribute();
|
throw invalid_attribute();
|
||||||
}
|
}
|
||||||
|
return *optional_ptr;
|
||||||
return value_ref();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -292,16 +241,21 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
bool operator==(const optional<T> &other) const noexcept
|
bool operator==(const optional<T> &other) const noexcept
|
||||||
{
|
{
|
||||||
if (has_value_ != other.has_value_)
|
if (optional_ptr == nullptr)
|
||||||
{
|
{
|
||||||
return false;
|
if (other.optional_ptr == nullptr) {
|
||||||
}
|
return true;
|
||||||
if (!has_value_)
|
} else {
|
||||||
{
|
return false;
|
||||||
return true;
|
};
|
||||||
}
|
} else {
|
||||||
// equality is overloaded to provide fuzzy equality when T is a fp number
|
if (other.optional_ptr == nullptr) {
|
||||||
return compare_equal(value_ref(), other.value_ref());
|
return false;
|
||||||
|
} else {
|
||||||
|
// equality is overloaded to provide fuzzy equality when T is a fp number
|
||||||
|
return compare_equal(*optional_ptr, *other.optional_ptr);
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -315,19 +269,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// helpers for getting a T out of storage
|
std::unique_ptr<T> optional_ptr;
|
||||||
T &value_ref() noexcept
|
|
||||||
{
|
|
||||||
return *reinterpret_cast<T *>(&storage_);
|
|
||||||
}
|
|
||||||
|
|
||||||
const T &value_ref() const noexcept
|
|
||||||
{
|
|
||||||
return *reinterpret_cast<const T *>(&storage_);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool has_value_;
|
|
||||||
typename std::aligned_storage<sizeof(T), alignof(T)>::type storage_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef XLNT_NOEXCEPT_VALUE_COMPAT
|
#ifdef XLNT_NOEXCEPT_VALUE_COMPAT
|
||||||
|
Loading…
x
Reference in New Issue
Block a user