From b004d0863c64d2fa0e6bada7bd6fe373baee393c Mon Sep 17 00:00:00 2001 From: Crzyrndm Date: Tue, 10 Jul 2018 17:26:34 +1200 Subject: [PATCH] address CI build failure Issue #300 Previous CI fix didn't work, try with type aliasing instead Issue #300 This reverts commit c87c0e39756062fbc761698e96978b0936005b0e. gcc 6 ok, msvc 14 choked Issue #300 noexcept(condition) doesn't seem to work on msvs 2015 Issue #300 Merge remote-tracking branch 'origin/dev-optional-no-default-ctor' into dev-resolve-simple-issues ensure uniqueness (uglify) and undefine compatibility macro --- include/xlnt/utils/optional.hpp | 53 ++++++++++++++++++++++++--------- tests/utils/optional_tests.cpp | 3 +- 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/include/xlnt/utils/optional.hpp b/include/xlnt/utils/optional.hpp index 75fd4ac5..bc02407d 100644 --- a/include/xlnt/utils/optional.hpp +++ b/include/xlnt/utils/optional.hpp @@ -25,6 +25,7 @@ #include #include +#include namespace xlnt { @@ -36,6 +37,26 @@ namespace xlnt { template class optional { +#if _MSC_VER <= 1900 // v14, visual studio 2015 +#define XLNT_NOEXCEPT_VALUE_COMPAT(...) (false) + using ctor_copy_T_noexcept = std::false_type; + using ctor_move_T_noexcept = std::false_type; + using copy_ctor_noexcept = ctor_copy_T_noexcept; + using move_ctor_noexcept = ctor_move_T_noexcept; + using set_copy_noexcept_t = std::false_type; + using set_move_noexcept_t = std::false_type; + using clear_noexcept_t = std::false_type; +#else +#define XLNT_NOEXCEPT_VALUE_COMPAT(...) (__VA_ARGS__) + using ctor_copy_T_noexcept = typename std::conditional{}, std::true_type, std::false_type>::type; + using ctor_move_T_noexcept = typename std::conditional{}, std::true_type, std::false_type>::type; + using copy_ctor_noexcept = ctor_copy_T_noexcept; + using move_ctor_noexcept = ctor_move_T_noexcept; + using set_copy_noexcept_t = typename std::conditional{} && std::is_nothrow_assignable{}, std::true_type, std::false_type>::type; + using set_move_noexcept_t = typename std::conditional{} && std::is_nothrow_move_assignable{}, std::true_type, std::false_type>::type; + using clear_noexcept_t = typename std::conditional{}, std::true_type, std::false_type>::type; +#endif + public: /// /// Default contructor. is_set() will be false initially. @@ -49,7 +70,7 @@ public: /// Constructs this optional with a value. /// noexcept if T copy ctor is noexcept /// - optional(const T &value) noexcept(std::is_nothrow_copy_constructible{}) + optional(const T &value) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(ctor_copy_T_noexcept{})) : has_value_(true) { new (&storage_) T(value); @@ -59,7 +80,7 @@ public: /// Constructs this optional with a value. /// noexcept if T move ctor is noexcept /// - optional(T &&value) noexcept(std::is_nothrow_move_constructible{}) + optional(T &&value) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(ctor_move_T_noexcept{})) : has_value_(true) { new (&storage_) T(std::move(value)); @@ -69,7 +90,7 @@ public: /// Copy constructs this optional from other /// noexcept if T copy ctor is noexcept /// - optional(const optional& other) noexcept(std::is_nothrow_copy_constructible{}) + optional(const optional &other) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(copy_ctor_noexcept{})) : has_value_(other.has_value_) { if (has_value_) @@ -82,7 +103,7 @@ public: /// Move constructs this optional from other. Clears the value from other if set /// noexcept if T move ctor is noexcept /// - optional(optional &&other) noexcept(std::is_nothrow_move_constructible{}) + optional(optional &&other) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(move_ctor_noexcept{})) : has_value_(other.has_value_) { if (has_value_) @@ -96,7 +117,7 @@ public: /// Copy assignment of this optional from other /// noexcept if set and clear are noexcept for T& /// - optional &operator=(const optional &other) noexcept(noexcept(set(std::declval())) && noexcept(clear())) + optional &operator=(const optional &other) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(set_copy_noexcept_t{} && clear_noexcept_t{})) { if (other.has_value_) { @@ -113,7 +134,7 @@ public: /// Move assignment of this optional from other /// noexcept if set and clear are noexcept for T&& /// - optional &operator=(optional &&other) noexcept(noexcept(set(std::declval())) && noexcept(clear())) + optional &operator=(optional &&other) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(set_move_noexcept_t{} && clear_noexcept_t{})) { if (other.has_value_) { @@ -147,7 +168,7 @@ public: /// /// Copies the value into the stored value /// - void set(const T &value) noexcept(std::is_nothrow_copy_constructible{} && std::is_nothrow_assignable{}) + void set(const T &value) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(set_copy_noexcept_t{})) { if (has_value_) { @@ -163,7 +184,7 @@ public: /// /// Moves the value into the stored value /// - void set(T &&value) noexcept(std::is_nothrow_move_constructible{} && std::is_nothrow_move_assignable{}) + void set(T &&value) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(set_move_noexcept_t{})) { // note seperate overload for two reasons (as opposed to perfect forwarding) // 1. have to deal with implicit conversions internally with perfect forwarding @@ -183,7 +204,7 @@ public: /// /// Assignment operator overload. Equivalent to setting the value using optional::set. /// - optional &operator=(const T &rhs) noexcept(noexcept(set(std::declval()))) + optional &operator=(const T &rhs) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(set_copy_noexcept_t{})) { set(rhs); return *this; @@ -192,7 +213,7 @@ public: /// /// Assignment operator overload. Equivalent to setting the value using optional::set. /// - optional &operator=(T &&rhs) noexcept(noexcept(set(std::declval()))) + optional &operator=(T &&rhs) noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(set_move_noexcept_t{})) { set(std::move(rhs)); return *this; @@ -201,7 +222,7 @@ public: /// /// After this is called, is_set() will return false until a new value is provided. /// - void clear() noexcept(std::is_nothrow_destructible{}) + void clear() noexcept(XLNT_NOEXCEPT_VALUE_COMPAT(clear_noexcept_t{})) { if (has_value_) { @@ -268,12 +289,12 @@ public: private: // helpers for getting a T out of storage - T & value_ref() + T &value_ref() noexcept { return *reinterpret_cast(&storage_); } - const T &value_ref() const + const T &value_ref() const noexcept { return *reinterpret_cast(&storage_); } @@ -282,4 +303,8 @@ private: typename std::aligned_storage::type storage_; }; -} // namespace xlnt +#ifdef XLNT_NOEXCEPT_VALUE_COMPAT +#undef XLNT_NOEXCEPT_VALUE_COMPAT +#endif + +} // namespace xlnt \ No newline at end of file diff --git a/tests/utils/optional_tests.cpp b/tests/utils/optional_tests.cpp index 1b32af87..6313e167 100644 --- a/tests/utils/optional_tests.cpp +++ b/tests/utils/optional_tests.cpp @@ -21,9 +21,8 @@ // @license: http://www.opensource.org/licenses/mit-license.php // @author: see AUTHORS file -#pragma once - #include +#include #include // test helpers