diff --git a/ThirdPartyNotices.txt b/ThirdPartyNotices.txt index 1ec00976fe..7127e787e5 100644 --- a/ThirdPartyNotices.txt +++ b/ThirdPartyNotices.txt @@ -31,8 +31,6 @@ sigslot wpiutil/src/main/native/include/wpi/Signal.h wpiutil/src/test/native/cpp/sigslot/ tcpsockets wpiutil/src/main/native/cpp/TCP{Stream,Connector,Acceptor}.cpp wpiutil/src/main/native/include/wpi/TCP*.h -Optional wpiutil/src/main/native/include/wpi/optional.h - wpiutil/src/test/native/cpp/test_optional.cpp Bootstrap wpiutil/src/main/native/resources/bootstrap-* CoreUI wpiutil/src/main/native/resources/coreui-* Feather Icons wpiutil/src/main/native/resources/feather-* @@ -221,36 +219,6 @@ See the License for the specific language governing permissions and limitations under the License. -============================================================================== -Optional License -============================================================================== -Copyright (C) 2011 - 2017 Andrzej Krzemienski. - -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - - ============================================================================== Bootstrap License ============================================================================== diff --git a/wpiutil/.styleguide b/wpiutil/.styleguide index a8ae9cd2e7..3cb0ebc2e9 100644 --- a/wpiutil/.styleguide +++ b/wpiutil/.styleguide @@ -61,8 +61,6 @@ generatedFileExclude { src/main/native/include/uv\.h$ src/main/native/include/uv/ src/main/native/libuv/ - src/main/native/include/wpi/optional\.h$ - src/test/native/cpp/test_optional\.cpp$ src/main/native/resources/ } diff --git a/wpiutil/src/main/native/cpp/llvm/NativeFormatting.cpp b/wpiutil/src/main/native/cpp/llvm/NativeFormatting.cpp index 41c43e2435..985e269d58 100644 --- a/wpiutil/src/main/native/cpp/llvm/NativeFormatting.cpp +++ b/wpiutil/src/main/native/cpp/llvm/NativeFormatting.cpp @@ -132,7 +132,7 @@ void wpi::write_integer(raw_ostream &S, long long N, size_t MinDigits, } void wpi::write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style, - optional Width) { + std::optional Width) { const size_t kMaxWidth = 128u; size_t W = std::min(kMaxWidth, Width.value_or(0u)); @@ -162,7 +162,7 @@ void wpi::write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style, } void wpi::write_double(raw_ostream &S, double N, FloatStyle Style, - optional Precision) { + std::optional Precision) { size_t Prec = Precision.value_or(getDefaultPrecision(Style)); if (std::isnan(N)) { diff --git a/wpiutil/src/main/native/include/wpi/ArrayRef.h b/wpiutil/src/main/native/include/wpi/ArrayRef.h index 5b50563be5..051a248018 100644 --- a/wpiutil/src/main/native/include/wpi/ArrayRef.h +++ b/wpiutil/src/main/native/include/wpi/ArrayRef.h @@ -11,7 +11,6 @@ #define WPIUTIL_WPI_ARRAYREF_H #include "wpi/Hashing.h" -#include "wpi/optional.h" #include "wpi/SmallVector.h" #include "wpi/STLExtras.h" #include "wpi/Compiler.h" @@ -22,6 +21,7 @@ #include #include #include +#include #include #include @@ -62,7 +62,7 @@ namespace wpi { /*implicit*/ ArrayRef() = default; /// Construct an empty ArrayRef from nullopt. - /*implicit*/ ArrayRef(nullopt_t) {} + /*implicit*/ ArrayRef(std::nullopt_t) {} /// Construct an ArrayRef from a single element. /*implicit*/ ArrayRef(const T &OneElt) @@ -298,7 +298,7 @@ namespace wpi { /*implicit*/ MutableArrayRef() = default; /// Construct an empty MutableArrayRef from nullopt. - /*implicit*/ MutableArrayRef(nullopt_t) : ArrayRef() {} + /*implicit*/ MutableArrayRef(std::nullopt_t) : ArrayRef() {} /// Construct an MutableArrayRef from a single element. /*implicit*/ MutableArrayRef(T &OneElt) : ArrayRef(OneElt) {} diff --git a/wpiutil/src/main/native/include/wpi/Format.h b/wpiutil/src/main/native/include/wpi/Format.h index 0a97ab03ca..2e38b587db 100644 --- a/wpiutil/src/main/native/include/wpi/Format.h +++ b/wpiutil/src/main/native/include/wpi/Format.h @@ -29,6 +29,7 @@ #include #include #include +#include #include namespace wpi { @@ -223,7 +224,7 @@ class FormattedBytes { ArrayRef Bytes; // If not nullopt, display offsets for each line relative to starting value. - optional FirstByteOffset; + std::optional FirstByteOffset; uint32_t IndentLevel; // Number of characters to indent each line. uint32_t NumPerLine; // Number of bytes to show per line. uint8_t ByteGroupSize; // How many hex bytes are grouped without spaces @@ -232,7 +233,7 @@ class FormattedBytes { friend class raw_ostream; public: - FormattedBytes(ArrayRef B, uint32_t IL, optional O, + FormattedBytes(ArrayRef B, uint32_t IL, std::optional O, uint32_t NPL, uint8_t BGS, bool U, bool A) : Bytes(B), FirstByteOffset(O), IndentLevel(IL), NumPerLine(NPL), ByteGroupSize(BGS), Upper(U), ASCII(A) { @@ -243,7 +244,7 @@ public: }; inline FormattedBytes -format_bytes(ArrayRef Bytes, optional FirstByteOffset = nullopt, +format_bytes(ArrayRef Bytes, std::optional FirstByteOffset = std::nullopt, uint32_t NumPerLine = 16, uint8_t ByteGroupSize = 4, uint32_t IndentLevel = 0, bool Upper = false) { return FormattedBytes(Bytes, IndentLevel, FirstByteOffset, NumPerLine, @@ -252,7 +253,7 @@ format_bytes(ArrayRef Bytes, optional FirstByteOffset = nullo inline FormattedBytes format_bytes_with_ascii(ArrayRef Bytes, - optional FirstByteOffset = nullopt, + std::optional FirstByteOffset = std::nullopt, uint32_t NumPerLine = 16, uint8_t ByteGroupSize = 4, uint32_t IndentLevel = 0, bool Upper = false) { return FormattedBytes(Bytes, IndentLevel, FirstByteOffset, NumPerLine, diff --git a/wpiutil/src/main/native/include/wpi/NativeFormatting.h b/wpiutil/src/main/native/include/wpi/NativeFormatting.h index 3407e75fa7..976adc8c99 100644 --- a/wpiutil/src/main/native/include/wpi/NativeFormatting.h +++ b/wpiutil/src/main/native/include/wpi/NativeFormatting.h @@ -10,10 +10,10 @@ #ifndef WPIUTIL_WPI_NATIVE_FORMATTING_H #define WPIUTIL_WPI_NATIVE_FORMATTING_H -#include "wpi/optional.h" #include "wpi/raw_ostream.h" #include +#include namespace wpi { enum class FloatStyle { Exponent, ExponentUpper, Fixed, Percent }; @@ -40,9 +40,9 @@ void write_integer(raw_ostream &S, long long N, size_t MinDigits, IntegerStyle Style); void write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style, - optional Width = nullopt); + std::optional Width = std::nullopt); void write_double(raw_ostream &S, double D, FloatStyle Style, - optional Precision = nullopt); + std::optional Precision = std::nullopt); } #endif diff --git a/wpiutil/src/main/native/include/wpi/STLExtras.h b/wpiutil/src/main/native/include/wpi/STLExtras.h index a26a8e279b..3e85e2c6fc 100644 --- a/wpiutil/src/main/native/include/wpi/STLExtras.h +++ b/wpiutil/src/main/native/include/wpi/STLExtras.h @@ -20,7 +20,6 @@ #include "wpi/SmallVector.h" #include "wpi/iterator.h" #include "wpi/iterator_range.h" -#include "wpi/optional.h" #include "wpi/ErrorHandling.h" #include #include @@ -32,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -595,16 +595,16 @@ static Iter next_or_end(const Iter &I, const Iter &End) { template static auto deref_or_none(const Iter &I, const Iter &End) - -> wpi::optional std::optional::type>::type> { if (I == End) - return nullopt; + return std::nullopt; return *I; } template struct ZipLongestItemType { using type = - wpi::optional())>::type>::type>; }; @@ -702,7 +702,7 @@ public: } // namespace detail /// Iterate over two or more iterators at the same time. Iteration continues -/// until all iterators reach the end. The wpi::optional only contains a value +/// until all iterators reach the end. The std::optional only contains a value /// if the iterator has not reached the end. template detail::zip_longest_range zip_longest(T &&t, U &&u, diff --git a/wpiutil/src/main/native/include/wpi/SmallSet.h b/wpiutil/src/main/native/include/wpi/SmallSet.h index 86662ac661..dca204e5e9 100644 --- a/wpiutil/src/main/native/include/wpi/SmallSet.h +++ b/wpiutil/src/main/native/include/wpi/SmallSet.h @@ -14,7 +14,6 @@ #ifndef WPIUTIL_WPI_SMALLSET_H #define WPIUTIL_WPI_SMALLSET_H -#include "wpi/optional.h" #include "wpi/SmallPtrSet.h" #include "wpi/SmallVector.h" #include "wpi/Compiler.h" @@ -22,6 +21,7 @@ #include "wpi/type_traits.h" #include #include +#include #include #include #include @@ -178,16 +178,16 @@ public: /// concept. // FIXME: Add iterators that abstract over the small and large form, and then // return those here. - std::pair insert(const T &V) { + std::pair insert(const T &V) { if (!isSmall()) - return std::make_pair(nullopt, Set.insert(V).second); + return std::make_pair(std::nullopt, Set.insert(V).second); VIterator I = vfind(V); if (I != Vector.end()) // Don't reinsert if it already exists. - return std::make_pair(nullopt, false); + return std::make_pair(std::nullopt, false); if (Vector.size() < N) { Vector.push_back(V); - return std::make_pair(nullopt, true); + return std::make_pair(std::nullopt, true); } // Otherwise, grow from vector to set. @@ -196,7 +196,7 @@ public: Vector.pop_back(); } Set.insert(V); - return std::make_pair(nullopt, true); + return std::make_pair(std::nullopt, true); } template diff --git a/wpiutil/src/main/native/include/wpi/VersionTuple.h b/wpiutil/src/main/native/include/wpi/VersionTuple.h index d37ee50cfa..e54ca924f5 100644 --- a/wpiutil/src/main/native/include/wpi/VersionTuple.h +++ b/wpiutil/src/main/native/include/wpi/VersionTuple.h @@ -16,8 +16,8 @@ #define WPIUTIL_WPI_VERSIONTUPLE_H #include "wpi/StringRef.h" -#include "wpi/optional.h" #include "wpi/raw_ostream.h" +#include #include #include @@ -68,23 +68,23 @@ public: unsigned getMajor() const { return Major; } /// Retrieve the minor version number, if provided. - optional getMinor() const { + std::optional getMinor() const { if (!HasMinor) - return nullopt; + return std::nullopt; return Minor; } /// Retrieve the subminor version number, if provided. - optional getSubminor() const { + std::optional getSubminor() const { if (!HasSubminor) - return nullopt; + return std::nullopt; return Subminor; } /// Retrieve the build version number, if provided. - optional getBuild() const { + std::optional getBuild() const { if (!HasBuild) - return nullopt; + return std::nullopt; return Build; } diff --git a/wpiutil/src/main/native/include/wpi/optional.h b/wpiutil/src/main/native/include/wpi/optional.h index 1257172370..a92f22ca47 100644 --- a/wpiutil/src/main/native/include/wpi/optional.h +++ b/wpiutil/src/main/native/include/wpi/optional.h @@ -1,917 +1,35 @@ -// Copyright (C) 2011 - 2012 Andrzej Krzemienski. -// -// Use, modification, and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// The idea and interface is based on Boost.Optional library -// authored by Fernando Luis Cacciola Carballal +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2019 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ -# ifndef WPIUTIL_WPI_OPTIONAL_H -# define WPIUTIL_WPI_OPTIONAL_H +#ifndef WPIUTIL_WPI_OPTIONAL_H_ +#define WPIUTIL_WPI_OPTIONAL_H_ -#ifdef _WIN32 -#define _SILENCE_CXX17_ADAPTOR_TYPEDEFS_DEPRECATION_WARNING -#endif +// clang-format off -# include -# include -# include -# include -# include -# include -# include - -# define TR2_OPTIONAL_REQUIRES(...) typename std::enable_if<__VA_ARGS__::value, bool>::type = false - -# if defined __GNUC__ || (defined _MSC_VER) && (_MSC_VER >= 1910) -# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 1 -# define OPTIONAL_CONSTEXPR_INIT_LIST constexpr -# else -# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 0 -# define OPTIONAL_CONSTEXPR_INIT_LIST -# endif - -# if defined __clang__ && (defined __cplusplus) && (__cplusplus != 201103L) -# define OPTIONAL_HAS_MOVE_ACCESSORS 1 -# else -# define OPTIONAL_HAS_MOVE_ACCESSORS 0 -# endif - -namespace wpi{ - -// 20.5.4, optional for object types -template class optional; - -// 20.5.5, optional for lvalue reference types -template class optional; - - -// workaround: std utility functions aren't constexpr yet -template inline constexpr T&& constexpr_forward(typename std::remove_reference::type& t) noexcept -{ - return static_cast(t); -} - -template inline constexpr T&& constexpr_forward(typename std::remove_reference::type&& t) noexcept -{ - static_assert(!std::is_lvalue_reference::value, "!!"); - return static_cast(t); -} - -template inline constexpr typename std::remove_reference::type&& constexpr_move(T&& t) noexcept -{ - return static_cast::type&&>(t); -} - - -#if defined NDEBUG -# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR) +#ifdef _MSC_VER +#pragma message("warning: wpi/optional.h is deprecated; include instead") #else -# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([]{assert(!#CHECK);}(), (EXPR))) +#warning "wpi/optional.h is deprecated; include instead" #endif +#include -namespace detail_ -{ +namespace wpi { -// static_addressof: a constexpr version of addressof template -struct has_overloaded_addressof -{ - template - constexpr static bool has_overload(...) { return false; } +using optional [[deprecated("use std::optional")]] = std::optional; - template ().operator&()) > - constexpr static bool has_overload(bool) { return true; } +using nullopt_t [[deprecated("use std::nullopt_t")]] = std::nullopt_t; - constexpr static bool value = has_overload(true); -}; +[[deprecated("use std::nullopt")]] inline constexpr std::nullopt_t nullopt = + std::nullopt; -template )> -constexpr T* static_addressof(T& ref) -{ - return &ref; -} +} // namespace wpi -template )> -T* static_addressof(T& ref) -{ - return std::addressof(ref); -} +// clang-format on - -// the call to convert(b) has return type A and converts b to type A iff b decltype(b) is implicitly convertible to A -template -constexpr U convert(U v) { return v; } - - -namespace swap_ns -{ - using std::swap; - - template - void adl_swap(T& t, T& u) noexcept(noexcept(swap(t, u))) - { - swap(t, u); - } - -} // namespace swap_ns - -} // namespace detail - - -constexpr struct trivial_init_t{} trivial_init{}; - - -// 20.5.6, In-place construction -constexpr struct in_place_t{} in_place{}; - - -// 20.5.7, Disengaged state indicator -struct nullopt_t -{ - struct init{}; - constexpr explicit nullopt_t(init){} -}; -constexpr nullopt_t nullopt{nullopt_t::init()}; - - -// 20.5.8, class bad_optional_access -class bad_optional_access : public std::logic_error { -public: - explicit bad_optional_access(const std::string& what_arg) : logic_error{what_arg} {} - explicit bad_optional_access(const char* what_arg) : logic_error{what_arg} {} -}; - - -template -union storage_t -{ - unsigned char dummy_; - T value_; - - constexpr storage_t( trivial_init_t ) noexcept : dummy_() {}; - - template - constexpr storage_t( Args&&... args ) : value_(constexpr_forward(args)...) {} - - ~storage_t(){} -}; - - -template -union constexpr_storage_t -{ - unsigned char dummy_; - T value_; - - constexpr constexpr_storage_t( trivial_init_t ) noexcept : dummy_() {}; - - template - constexpr constexpr_storage_t( Args&&... args ) : value_(constexpr_forward(args)...) {} - - ~constexpr_storage_t() = default; -}; - - -template -struct optional_base -{ - bool init_; - storage_t storage_; - - constexpr optional_base() noexcept : init_(false), storage_(trivial_init) {}; - - explicit constexpr optional_base(const T& v) : init_(true), storage_(v) {} - - explicit constexpr optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {} - - template explicit optional_base(in_place_t, Args&&... args) - : init_(true), storage_(constexpr_forward(args)...) {} - - template >)> - explicit optional_base(in_place_t, std::initializer_list il, Args&&... args) - : init_(true), storage_(il, std::forward(args)...) {} - - ~optional_base() { if (init_) storage_.value_.T::~T(); } -}; - - -template -struct constexpr_optional_base -{ - bool init_; - constexpr_storage_t storage_; - - constexpr constexpr_optional_base() noexcept : init_(false), storage_(trivial_init) {}; - - explicit constexpr constexpr_optional_base(const T& v) : init_(true), storage_(v) {} - - explicit constexpr constexpr_optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {} - - template explicit constexpr constexpr_optional_base(in_place_t, Args&&... args) - : init_(true), storage_(constexpr_forward(args)...) {} - - template >)> - OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, std::initializer_list il, Args&&... args) - : init_(true), storage_(il, std::forward(args)...) {} - - ~constexpr_optional_base() = default; -}; - -template -using OptionalBase = typename std::conditional< - std::is_trivially_destructible::value, // if possible - constexpr_optional_base::type>, // use base with trivial destructor - optional_base::type> ->::type; - - - -template -class optional : private OptionalBase -{ - static_assert( !std::is_same::type, nullopt_t>::value, "bad T" ); - static_assert( !std::is_same::type, in_place_t>::value, "bad T" ); - - - constexpr bool initialized() const noexcept { return OptionalBase::init_; } - typename std::remove_const::type* dataptr() { return std::addressof(OptionalBase::storage_.value_); } - constexpr const T* dataptr() const { return detail_::static_addressof(OptionalBase::storage_.value_); } - - constexpr const T& contained_val() const& { return OptionalBase::storage_.value_; } -# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 - constexpr T&& contained_val() && { return std::move(OptionalBase::storage_.value_); } - constexpr T& contained_val() & { return OptionalBase::storage_.value_; } -# else - T& contained_val() & { return OptionalBase::storage_.value_; } - T&& contained_val() && { return std::move(OptionalBase::storage_.value_); } -# endif - - void clear() noexcept { - if (initialized()) dataptr()->T::~T(); - OptionalBase::init_ = false; - } - - template - void initialize(Args&&... args) noexcept(noexcept(T(std::forward(args)...))) - { - assert(!OptionalBase::init_); - ::new (static_cast(dataptr())) T(std::forward(args)...); - OptionalBase::init_ = true; - } - - template - void initialize(std::initializer_list il, Args&&... args) noexcept(noexcept(T(il, std::forward(args)...))) - { - assert(!OptionalBase::init_); - ::new (static_cast(dataptr())) T(il, std::forward(args)...); - OptionalBase::init_ = true; - } - -public: - typedef T value_type; - - // 20.5.5.1, constructors - constexpr optional() noexcept : OptionalBase() {}; - constexpr optional(nullopt_t) noexcept : OptionalBase() {}; - - optional(const optional& rhs) - : OptionalBase() - { - if (rhs.initialized()) { - ::new (static_cast(dataptr())) T(*rhs); - OptionalBase::init_ = true; - } - } - - optional(optional&& rhs) noexcept(std::is_nothrow_move_constructible::value) - : OptionalBase() - { - if (rhs.initialized()) { - ::new (static_cast(dataptr())) T(std::move(*rhs)); - OptionalBase::init_ = true; - } - } - - constexpr optional(const T& v) : OptionalBase(v) {} - - constexpr optional(T&& v) : OptionalBase(constexpr_move(v)) {} - - template - explicit constexpr optional(in_place_t, Args&&... args) - : OptionalBase(in_place_t{}, constexpr_forward(args)...) {} - - template >)> - OPTIONAL_CONSTEXPR_INIT_LIST explicit optional(in_place_t, std::initializer_list il, Args&&... args) - : OptionalBase(in_place_t{}, il, constexpr_forward(args)...) {} - - // 20.5.4.2, Destructor - ~optional() = default; - - // 20.5.4.3, assignment - optional& operator=(nullopt_t) noexcept - { - clear(); - return *this; - } - - optional& operator=(const optional& rhs) - { - if (initialized() == true && rhs.initialized() == false) clear(); - else if (initialized() == false && rhs.initialized() == true) initialize(*rhs); - else if (initialized() == true && rhs.initialized() == true) contained_val() = *rhs; - return *this; - } - - optional& operator=(optional&& rhs) - noexcept(std::is_nothrow_move_assignable::value && std::is_nothrow_move_constructible::value) - { - if (initialized() == true && rhs.initialized() == false) clear(); - else if (initialized() == false && rhs.initialized() == true) initialize(std::move(*rhs)); - else if (initialized() == true && rhs.initialized() == true) contained_val() = std::move(*rhs); - return *this; - } - - template - auto operator=(U&& v) - -> typename std::enable_if - < - std::is_same::type, T>::value, - optional& - >::type - { - if (initialized()) { contained_val() = std::forward(v); } - else { initialize(std::forward(v)); } - return *this; - } - - - template - void emplace(Args&&... args) - { - clear(); - initialize(std::forward(args)...); - } - - template - void emplace(std::initializer_list il, Args&&... args) - { - clear(); - initialize(il, std::forward(args)...); - } - - // 20.5.4.4, Swap - void swap(optional& rhs) noexcept(std::is_nothrow_move_constructible::value - && noexcept(detail_::swap_ns::adl_swap(std::declval(), std::declval()))) - { - if (initialized() == true && rhs.initialized() == false) { rhs.initialize(std::move(**this)); clear(); } - else if (initialized() == false && rhs.initialized() == true) { initialize(std::move(*rhs)); rhs.clear(); } - else if (initialized() == true && rhs.initialized() == true) { using std::swap; swap(**this, *rhs); } - } - - // 20.5.4.5, Observers - - explicit constexpr operator bool() const noexcept { return initialized(); } - constexpr bool has_value() const noexcept { return initialized(); } - - constexpr T const* operator ->() const { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr()); - } - -# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 - - constexpr T* operator ->() { - assert (initialized()); - return dataptr(); - } - - constexpr T const& operator *() const& { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); - } - - constexpr T& operator *() & { - assert (initialized()); - return contained_val(); - } - - constexpr T&& operator *() && { - assert (initialized()); - return constexpr_move(contained_val()); - } - - constexpr T const& value() const& { - return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); - } - - constexpr T& value() & { - return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); - } - - constexpr T&& value() && { - if (!initialized()) throw bad_optional_access("bad optional access"); - return std::move(contained_val()); - } - -# else - - T* operator ->() { - assert (initialized()); - return dataptr(); - } - - constexpr T const& operator *() const { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); - } - - T& operator *() { - assert (initialized()); - return contained_val(); - } - - constexpr T const& value() const { - return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); - } - - T& value() { - return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); - } - -# endif - - template - constexpr T value_or(V&& v) const& - { - return *this ? **this : detail_::convert(constexpr_forward(v)); - } - -# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 - - template - constexpr T value_or(V&& v) && - { - return *this ? constexpr_move(const_cast&>(*this).contained_val()) : detail_::convert(constexpr_forward(v)); - } - -# else - - template - T value_or(V&& v) && - { - return *this ? constexpr_move(const_cast&>(*this).contained_val()) : detail_::convert(constexpr_forward(v)); - } - -# endif - - // 20.6.3.6, modifiers - void reset() noexcept { clear(); } -}; - - -template -class optional -{ - static_assert( !std::is_same::value, "bad T" ); - static_assert( !std::is_same::value, "bad T" ); - T* ref; - -public: - - // 20.5.5.1, construction/destruction - constexpr optional() noexcept : ref(nullptr) {} - - constexpr optional(nullopt_t) noexcept : ref(nullptr) {} - - constexpr optional(T& v) noexcept : ref(detail_::static_addressof(v)) {} - - optional(T&&) = delete; - - constexpr optional(const optional& rhs) noexcept : ref(rhs.ref) {} - - explicit constexpr optional(in_place_t, T& v) noexcept : ref(detail_::static_addressof(v)) {} - - explicit optional(in_place_t, T&&) = delete; - - ~optional() = default; - - // 20.5.5.2, mutation - optional& operator=(nullopt_t) noexcept { - ref = nullptr; - return *this; - } - - // optional& operator=(const optional& rhs) noexcept { - // ref = rhs.ref; - // return *this; - // } - - // optional& operator=(optional&& rhs) noexcept { - // ref = rhs.ref; - // return *this; - // } - - template - auto operator=(U&& rhs) noexcept - -> typename std::enable_if - < - std::is_same::type, optional>::value, - optional& - >::type - { - ref = rhs.ref; - return *this; - } - - template - auto operator=(U&& rhs) noexcept - -> typename std::enable_if - < - !std::is_same::type, optional>::value, - optional& - >::type - = delete; - - void emplace(T& v) noexcept { - ref = detail_::static_addressof(v); - } - - void emplace(T&&) = delete; - - - void swap(optional& rhs) noexcept - { - std::swap(ref, rhs.ref); - } - - // 20.5.5.3, observers - constexpr T* operator->() const { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref); - } - - constexpr T& operator*() const { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref); - } - - constexpr T& value() const { - return ref ? *ref : (throw bad_optional_access("bad optional access"), *ref); - } - - explicit constexpr operator bool() const noexcept { - return ref != nullptr; - } - - constexpr bool has_value() const noexcept { - return ref != nullptr; - } - - template - constexpr typename std::decay::type value_or(V&& v) const - { - return *this ? **this : detail_::convert::type>(constexpr_forward(v)); - } - - // x.x.x.x, modifiers - void reset() noexcept { ref = nullptr; } -}; - - -template -class optional -{ - static_assert( sizeof(T) == 0, "optional rvalue references disallowed" ); -}; - - -// 20.5.8, Relational operators -template constexpr bool operator==(const optional& x, const optional& y) -{ - return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y; -} - -template constexpr bool operator!=(const optional& x, const optional& y) -{ - return !(x == y); -} - -template constexpr bool operator<(const optional& x, const optional& y) -{ - return (!y) ? false : (!x) ? true : *x < *y; -} - -template constexpr bool operator>(const optional& x, const optional& y) -{ - return (y < x); -} - -template constexpr bool operator<=(const optional& x, const optional& y) -{ - return !(y < x); -} - -template constexpr bool operator>=(const optional& x, const optional& y) -{ - return !(x < y); -} - - -// 20.5.9, Comparison with nullopt -template constexpr bool operator==(const optional& x, nullopt_t) noexcept -{ - return (!x); -} - -template constexpr bool operator==(nullopt_t, const optional& x) noexcept -{ - return (!x); -} - -template constexpr bool operator!=(const optional& x, nullopt_t) noexcept -{ - return bool(x); -} - -template constexpr bool operator!=(nullopt_t, const optional& x) noexcept -{ - return bool(x); -} - -template constexpr bool operator<(const optional&, nullopt_t) noexcept -{ - return false; -} - -template constexpr bool operator<(nullopt_t, const optional& x) noexcept -{ - return bool(x); -} - -template constexpr bool operator<=(const optional& x, nullopt_t) noexcept -{ - return (!x); -} - -template constexpr bool operator<=(nullopt_t, const optional&) noexcept -{ - return true; -} - -template constexpr bool operator>(const optional& x, nullopt_t) noexcept -{ - return bool(x); -} - -template constexpr bool operator>(nullopt_t, const optional&) noexcept -{ - return false; -} - -template constexpr bool operator>=(const optional&, nullopt_t) noexcept -{ - return true; -} - -template constexpr bool operator>=(nullopt_t, const optional& x) noexcept -{ - return (!x); -} - - - -// 20.5.10, Comparison with T -template constexpr bool operator==(const optional& x, const T& v) -{ - return bool(x) ? *x == v : false; -} - -template constexpr bool operator==(const T& v, const optional& x) -{ - return bool(x) ? v == *x : false; -} - -template constexpr bool operator!=(const optional& x, const T& v) -{ - return bool(x) ? *x != v : true; -} - -template constexpr bool operator!=(const T& v, const optional& x) -{ - return bool(x) ? v != *x : true; -} - -template constexpr bool operator<(const optional& x, const T& v) -{ - return bool(x) ? *x < v : true; -} - -template constexpr bool operator>(const T& v, const optional& x) -{ - return bool(x) ? v > *x : true; -} - -template constexpr bool operator>(const optional& x, const T& v) -{ - return bool(x) ? *x > v : false; -} - -template constexpr bool operator<(const T& v, const optional& x) -{ - return bool(x) ? v < *x : false; -} - -template constexpr bool operator>=(const optional& x, const T& v) -{ - return bool(x) ? *x >= v : false; -} - -template constexpr bool operator<=(const T& v, const optional& x) -{ - return bool(x) ? v <= *x : false; -} - -template constexpr bool operator<=(const optional& x, const T& v) -{ - return bool(x) ? *x <= v : true; -} - -template constexpr bool operator>=(const T& v, const optional& x) -{ - return bool(x) ? v >= *x : true; -} - - -// Comparison of optional with T -template constexpr bool operator==(const optional& x, const T& v) -{ - return bool(x) ? *x == v : false; -} - -template constexpr bool operator==(const T& v, const optional& x) -{ - return bool(x) ? v == *x : false; -} - -template constexpr bool operator!=(const optional& x, const T& v) -{ - return bool(x) ? *x != v : true; -} - -template constexpr bool operator!=(const T& v, const optional& x) -{ - return bool(x) ? v != *x : true; -} - -template constexpr bool operator<(const optional& x, const T& v) -{ - return bool(x) ? *x < v : true; -} - -template constexpr bool operator>(const T& v, const optional& x) -{ - return bool(x) ? v > *x : true; -} - -template constexpr bool operator>(const optional& x, const T& v) -{ - return bool(x) ? *x > v : false; -} - -template constexpr bool operator<(const T& v, const optional& x) -{ - return bool(x) ? v < *x : false; -} - -template constexpr bool operator>=(const optional& x, const T& v) -{ - return bool(x) ? *x >= v : false; -} - -template constexpr bool operator<=(const T& v, const optional& x) -{ - return bool(x) ? v <= *x : false; -} - -template constexpr bool operator<=(const optional& x, const T& v) -{ - return bool(x) ? *x <= v : true; -} - -template constexpr bool operator>=(const T& v, const optional& x) -{ - return bool(x) ? v >= *x : true; -} - -// Comparison of optional with T -template constexpr bool operator==(const optional& x, const T& v) -{ - return bool(x) ? *x == v : false; -} - -template constexpr bool operator==(const T& v, const optional& x) -{ - return bool(x) ? v == *x : false; -} - -template constexpr bool operator!=(const optional& x, const T& v) -{ - return bool(x) ? *x != v : true; -} - -template constexpr bool operator!=(const T& v, const optional& x) -{ - return bool(x) ? v != *x : true; -} - -template constexpr bool operator<(const optional& x, const T& v) -{ - return bool(x) ? *x < v : true; -} - -template constexpr bool operator>(const T& v, const optional& x) -{ - return bool(x) ? v > *x : true; -} - -template constexpr bool operator>(const optional& x, const T& v) -{ - return bool(x) ? *x > v : false; -} - -template constexpr bool operator<(const T& v, const optional& x) -{ - return bool(x) ? v < *x : false; -} - -template constexpr bool operator>=(const optional& x, const T& v) -{ - return bool(x) ? *x >= v : false; -} - -template constexpr bool operator<=(const T& v, const optional& x) -{ - return bool(x) ? v <= *x : false; -} - -template constexpr bool operator<=(const optional& x, const T& v) -{ - return bool(x) ? *x <= v : true; -} - -template constexpr bool operator>=(const T& v, const optional& x) -{ - return bool(x) ? v >= *x : true; -} - - -// 20.5.12, Specialized algorithms -template -void swap(optional& x, optional& y) noexcept(noexcept(x.swap(y))) -{ - x.swap(y); -} - - -template -constexpr optional::type> make_optional(T&& v) -{ - return optional::type>(constexpr_forward(v)); -} - -template -constexpr optional make_optional(std::reference_wrapper v) -{ - return optional(v.get()); -} - - -} // namespace wpi - -namespace std -{ - template - struct hash> - { - typedef typename hash::result_type result_type; - typedef wpi::optional argument_type; - - constexpr result_type operator()(argument_type const& arg) const { - return arg ? std::hash{}(*arg) : result_type{}; - } - }; - - template - struct hash> - { - typedef typename hash::result_type result_type; - typedef wpi::optional argument_type; - - constexpr result_type operator()(argument_type const& arg) const { - return arg ? std::hash{}(*arg) : result_type{}; - } - }; -} - -# undef TR2_OPTIONAL_REQUIRES -# undef TR2_OPTIONAL_ASSERTED_EXPRESSION - -# endif //WPIUTIL_WPI_OPTIONAL_H +#endif // WPIUTIL_WPI_OPTIONAL_H_ diff --git a/wpiutil/src/test/native/cpp/test_optional.cpp b/wpiutil/src/test/native/cpp/test_optional.cpp deleted file mode 100644 index e64f0c2a1f..0000000000 --- a/wpiutil/src/test/native/cpp/test_optional.cpp +++ /dev/null @@ -1,1523 +0,0 @@ -// Copyright (C) 2011 - 2017 Andrzej Krzemienski. -// -// Use, modification, and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// The idea and interface is based on Boost.Optional library -// authored by Fernando Luis Cacciola Carballal - -# include "wpi/optional.h" - -#include "gtest/gtest.h" - -# include -# include -# include -# include - - - -enum State -{ - sDefaultConstructed, - sValueCopyConstructed, - sValueMoveConstructed, - sCopyConstructed, - sMoveConstructed, - sMoveAssigned, - sCopyAssigned, - sValueCopyAssigned, - sValueMoveAssigned, - sMovedFrom, - sValueConstructed -}; - -struct OracleVal -{ - State s; - int i; - OracleVal(int i = 0) : s(sValueConstructed), i(i) {} -}; - -struct Oracle -{ - State s; - OracleVal val; - - Oracle() : s(sDefaultConstructed) {} - Oracle(const OracleVal& v) : s(sValueCopyConstructed), val(v) {} - Oracle(OracleVal&& v) : s(sValueMoveConstructed), val(std::move(v)) {v.s = sMovedFrom;} - Oracle(const Oracle& o) : s(sCopyConstructed), val(o.val) {} - Oracle(Oracle&& o) : s(sMoveConstructed), val(std::move(o.val)) {o.s = sMovedFrom;} - - Oracle& operator=(const OracleVal& v) { s = sValueCopyConstructed; val = v; return *this; } - Oracle& operator=(OracleVal&& v) { s = sValueMoveConstructed; val = std::move(v); v.s = sMovedFrom; return *this; } - Oracle& operator=(const Oracle& o) { s = sCopyConstructed; val = o.val; return *this; } - Oracle& operator=(Oracle&& o) { s = sMoveConstructed; val = std::move(o.val); o.s = sMovedFrom; return *this; } -}; - -struct Guard -{ - std::string val; - Guard() : val{} {} - explicit Guard(std::string s, int = 0) : val(s) {} - Guard(const Guard&) = delete; - Guard(Guard&&) = delete; - void operator=(const Guard&) = delete; - void operator=(Guard&&) = delete; -}; - -struct ExplicitStr -{ - std::string s; - explicit ExplicitStr(const char* chp) : s(chp) {}; -}; - -struct Date -{ - int i; - Date() = delete; - Date(int i) : i{i} {}; - Date(Date&& d) : i(d.i) { d.i = 0; } - Date(const Date&) = delete; - Date& operator=(const Date&) = delete; - Date& operator=(Date&& d) { i = d.i; d.i = 0; return *this;}; -}; - -bool operator==( Oracle const& a, Oracle const& b ) { return a.val.i == b.val.i; } -bool operator!=( Oracle const& a, Oracle const& b ) { return a.val.i != b.val.i; } - - -namespace tr2 = wpi; - - -TEST(Optional, disengaged_ctor) -{ - tr2::optional o1; - assert (!o1); - - tr2::optional o2 = tr2::nullopt; - assert (!o2); - - tr2::optional o3 = o2; - assert (!o3); - - assert (o1 == tr2::nullopt); - assert (o1 == tr2::optional{}); - assert (!o1); - assert (bool(o1) == false); - - assert (o2 == tr2::nullopt); - assert (o2 == tr2::optional{}); - assert (!o2); - assert (bool(o2) == false); - - assert (o3 == tr2::nullopt); - assert (o3 == tr2::optional{}); - assert (!o3); - assert (bool(o3) == false); - - assert (o1 == o2); - assert (o2 == o1); - assert (o1 == o3); - assert (o3 == o1); - assert (o2 == o3); - assert (o3 == o2); -} - - -TEST(Optional, value_ctor) -{ - OracleVal v; - tr2::optional oo1(v); - assert (oo1 != tr2::nullopt); - assert (oo1 != tr2::optional{}); - assert (oo1 == tr2::optional{v}); - assert (!!oo1); - assert (bool(oo1)); - // NA: assert (oo1->s == sValueCopyConstructed); - assert (oo1->s == sMoveConstructed); - assert (v.s == sValueConstructed); - - tr2::optional oo2(std::move(v)); - assert (oo2 != tr2::nullopt); - assert (oo2 != tr2::optional{}); - assert (oo2 == oo1); - assert (!!oo2); - assert (bool(oo2)); - // NA: assert (oo2->s == sValueMoveConstructed); - assert (oo2->s == sMoveConstructed); - assert (v.s == sMovedFrom); - - { - OracleVal v; - tr2::optional oo1{tr2::in_place, v}; - assert (oo1 != tr2::nullopt); - assert (oo1 != tr2::optional{}); - assert (oo1 == tr2::optional{v}); - assert (!!oo1); - assert (bool(oo1)); - assert (oo1->s == sValueCopyConstructed); - assert (v.s == sValueConstructed); - - tr2::optional oo2{tr2::in_place, std::move(v)}; - assert (oo2 != tr2::nullopt); - assert (oo2 != tr2::optional{}); - assert (oo2 == oo1); - assert (!!oo2); - assert (bool(oo2)); - assert (oo2->s == sValueMoveConstructed); - assert (v.s == sMovedFrom); - } -} - - -TEST(Optional, assignment) -{ - tr2::optional oi; - oi = tr2::optional{1}; - assert (*oi == 1); - - oi = tr2::nullopt; - assert (!oi); - - oi = 2; - assert (*oi == 2); - - oi = {}; - assert (!oi); -} - - -template -struct MoveAware -{ - T val; - bool moved; - MoveAware(T val) : val(val), moved(false) {} - MoveAware(MoveAware const&) = delete; - MoveAware(MoveAware&& rhs) : val(rhs.val), moved(rhs.moved) { - rhs.moved = true; - } - MoveAware& operator=(MoveAware const&) = delete; - MoveAware& operator=(MoveAware&& rhs) { - val = (rhs.val); - moved = (rhs.moved); - rhs.moved = true; - return *this; - } -}; - -TEST(Optional, moved_from_state) -{ - // first, test mock: - MoveAware i{1}, j{2}; - assert (i.val == 1); - assert (!i.moved); - assert (j.val == 2); - assert (!j.moved); - - MoveAware k = std::move(i); - assert (k.val == 1); - assert (!k.moved); - assert (i.val == 1); - assert (i.moved); - - k = std::move(j); - assert (k.val == 2); - assert (!k.moved); - assert (j.val == 2); - assert (j.moved); - - // now, test optional - tr2::optional> oi{1}, oj{2}; - assert (oi); - assert (!oi->moved); - assert (oj); - assert (!oj->moved); - - tr2::optional> ok = std::move(oi); - assert (ok); - assert (!ok->moved); - assert (oi); - assert (oi->moved); - - ok = std::move(oj); - assert (ok); - assert (!ok->moved); - assert (oj); - assert (oj->moved); -} - - -TEST(Optional, copy_move_ctor_optional_int) -{ - tr2::optional oi; - tr2::optional oj = oi; - - assert (!oj); - assert (oj == oi); - assert (oj == tr2::nullopt); - assert (!bool(oj)); - - oi = 1; - tr2::optional ok = oi; - assert (!!ok); - assert (bool(ok)); - assert (ok == oi); - assert (ok != oj); - assert (*ok == 1); - - tr2::optional ol = std::move(oi); - assert (!!ol); - assert (bool(ol)); - assert (ol == oi); - assert (ol != oj); - assert (*ol == 1); -} - - -TEST(Optional, optional_optional) -{ - tr2::optional> oi1 = tr2::nullopt; - assert (oi1 == tr2::nullopt); - assert (!oi1); - - { - tr2::optional> oi2 {tr2::in_place}; - assert (oi2 != tr2::nullopt); - assert (bool(oi2)); - assert (*oi2 == tr2::nullopt); - //assert (!(*oi2)); - //std::cout << typeid(**oi2).name() << std::endl; - } - - { - tr2::optional> oi2 {tr2::in_place, tr2::nullopt}; - assert (oi2 != tr2::nullopt); - assert (bool(oi2)); - assert (*oi2 == tr2::nullopt); - assert (!*oi2); - } - - { - tr2::optional> oi2 {tr2::optional{}}; - assert (oi2 != tr2::nullopt); - assert (bool(oi2)); - assert (*oi2 == tr2::nullopt); - assert (!*oi2); - } - - tr2::optional oi; - auto ooi = tr2::make_optional(oi); - static_assert( std::is_same>, decltype(ooi)>::value, ""); - -} - -TEST(Optional, example_guard) -{ - using namespace tr2; - //FAILS: optional ogx(Guard("res1")); - //FAILS: optional ogx = "res1"; - //FAILS: optional ogx("res1"); - optional oga; // Guard is non-copyable (and non-moveable) - optional ogb(in_place, "res1"); // initialzes the contained value with "res1" - assert (bool(ogb)); - assert (ogb->val == "res1"); - - optional ogc(in_place); // default-constructs the contained value - assert (bool(ogc)); - assert (ogc->val == ""); - - oga.emplace("res1"); // initialzes the contained value with "res1" - assert (bool(oga)); - assert (oga->val == "res1"); - - oga.emplace(); // destroys the contained value and - // default-constructs the new one - assert (bool(oga)); - assert (oga->val == ""); - - oga = nullopt; // OK: make disengaged the optional Guard - assert (!(oga)); - //FAILS: ogb = {}; // ERROR: Guard is not Moveable -} - - -void process(){} -void process(int ){} -void processNil(){} - - -TEST(Optional, example1) -{ - using namespace tr2; - optional oi; // create disengaged object - optional oj = nullopt; // alternative syntax - oi = oj; // assign disengaged object - optional ok = oj; // ok is disengaged - - if (oi) assert(false); // 'if oi is engaged...' - if (!oi) assert(true); // 'if oi is disengaged...' - - if (oi != nullopt) assert(false); // 'if oi is engaged...' - if (oi == nullopt) assert(true); // 'if oi is disengaged...' - - assert(oi == ok); // two disengaged optionals compare equal - - /////////////////////////////////////////////////////////////////////////// - optional ol{1}; // ol is engaged; its contained value is 1 - ok = 2; // ok becomes engaged; its contained value is 2 - oj = ol; // oj becomes engaged; its contained value is 1 - - assert(oi != ol); // disengaged != engaged - assert(ok != ol); // different contained values - assert(oj == ol); // same contained value - assert(oi < ol); // disengaged < engaged - assert(ol < ok); // less by contained value - - ///////////////////////////////////////////////////////////////////////////// - optional om{1}; // om is engaged; its contained value is 1 - optional on = om; // on is engaged; its contained value is 1 - om = 2; // om is engaged; its contained value is 2 - assert (on != om); // on still contains 3. They are not pointers - - ///////////////////////////////////////////////////////////////////////////// - int i = *ol; // i obtains the value contained in ol - assert (i == 1); - *ol = 9; // the object contained in ol becomes 9 - assert(*ol == 9); - assert(ol == make_optional(9)); - - /////////////////////////////////// - int p = 1; - optional op = p; - assert(*op == 1); - p = 2; - assert(*op == 1); // value contained in op is separated from p - - //////////////////////////////// - if (ol) - process(*ol); // use contained value if present - else - process(); // proceed without contained value - - if (!om) - processNil(); - else - process(*om); - - ///////////////////////////////////////// - process(ol.value_or(0)); // use 0 if ol is disengaged - - //////////////////////////////////////////// - ok = nullopt; // if ok was engaged calls T's dtor - oj = {}; // assigns a temporary disengaged optional -} - - -TEST(Optional, example_guard2) -{ - using wpi::optional; - const optional c = 4; - int i = *c; // i becomes 4 - assert (i == 4); - // FAILS: *c = i; // ERROR: cannot assign to const int& -} - - -TEST(Optional, example_ref) -{ - using namespace wpi; - int i = 1; - int j = 2; - optional ora; // disengaged optional reference to int - optional orb = i; // contained reference refers to object i - - *orb = 3; // i becomes 3 - // FAILS: ora = j; // ERROR: optional refs do not have assignment from T - // FAILS: ora = {j}; // ERROR: optional refs do not have copy/move assignment - // FAILS: ora = orb; // ERROR: no copy/move assignment - ora.emplace(j); // OK: contained reference refers to object j - ora.emplace(i); // OK: contained reference now refers to object i - - ora = nullopt; // OK: ora becomes disengaged -} - - -template -T getValue( tr2::optional newVal = tr2::nullopt, tr2::optional storeHere = tr2::nullopt ) -{ - T cached{}; - - if (newVal) { - cached = *newVal; - - if (storeHere) { - *storeHere = *newVal; // LEGAL: assigning T to T - } - } - return cached; -} - -TEST(Optional, example_optional_arg) -{ - int iii = 0; - iii = getValue(iii, iii); - iii = getValue(iii); - iii = getValue(); - - { - using namespace wpi; - optional grd1{in_place, "res1", 1}; // guard 1 initialized - optional grd2; - - grd2.emplace("res2", 2); // guard 2 initialized - grd1 = nullopt; // guard 1 released - - } // guard 2 released (in dtor) -} - - -std::tuple getStartMidEnd() { return std::tuple{Date{1}, Date{2}, Date{3}}; } -void run(Date const&, Date const&, Date const&) {} - -TEST(Optional, example_date) -{ - using namespace wpi; - optional start, mid, end; // Date doesn't have default ctor (no good default date) - - std::tie(start, mid, end) = getStartMidEnd(); - run(*start, *mid, *end); -} - - -wpi::optional readNextChar(){ return{}; } - -void run(wpi::optional) {} -void run(std::complex) {} - - -template -void assign_norebind(tr2::optional& optref, T& obj) -{ - if (optref) *optref = obj; - else optref.emplace(obj); -} - -template void unused(T&&) {} - -TEST(Optional, example_conceptual_model) -{ - using namespace wpi; - - optional oi = 0; - optional oj = 1; - optional ok = nullopt; - - oi = 1; - oj = nullopt; - ok = 0; - - unused(oi == nullopt); - unused(oj == 0); - unused(ok == 1); -} - -TEST(Optional, example_rationale) -{ - using namespace wpi; - if (optional ch = readNextChar()) { - unused(ch); - // ... - } - - ////////////////////////////////// - optional opt1 = nullopt; - optional opt2 = {}; - - opt1 = nullopt; - opt2 = {}; - - if (opt1 == nullopt) {} - if (!opt2) {} - if (opt2 == optional{}) {} - - - - //////////////////////////////// - - run(nullopt); // pick the second overload - // FAILS: run({}); // ambiguous - - if (opt1 == nullopt) {} // fine - // FAILS: if (opt2 == {}) {} // ilegal - - //////////////////////////////// - assert (optional{} < optional{0}); - assert (optional{0} < optional{1}); - assert (!(optional{} < optional{}) ); - assert (!(optional{1} < optional{1})); - - assert (optional{} != optional{0}); - assert (optional{0} != optional{1}); - assert (optional{} == optional{} ); - assert (optional{0} == optional{0}); - - ///////////////////////////////// - optional o; - o = make_optional(1); // copy/move assignment - o = 1; // assignment from T - o.emplace(1); // emplacement - - //////////////////////////////////// - int isas = 0, i = 9; - optional asas = i; - assign_norebind(asas, isas); - - ///////////////////////////////////// - ////tr2::optional> ov2 = {2, 3}; - ////assert (bool(ov2)); - ////assert ((*ov2)[1] == 3); - //// - //////////////////////////////// - ////std::vector v = {1, 2, 4, 8}; - ////optional> ov = {1, 2, 4, 8}; - - ////assert (v == *ov); - //// - ////ov = {1, 2, 4, 8}; - - ////std::allocator a; - ////optional> ou { in_place, {1, 2, 4, 8}, a }; - - ////assert (ou == ov); - - ////////////////////////////// - // inconvenient syntax: - { - - tr2::optional> ov2{tr2::in_place, {2, 3}}; - - assert (bool(ov2)); - assert ((*ov2)[1] == 3); - - //////////////////////////// - - std::vector v = {1, 2, 4, 8}; - optional> ov{tr2::in_place, {1, 2, 4, 8}}; - - assert (v == *ov); - - ov.emplace({1, 2, 4, 8}); -/* - std::allocator a; - optional> ou { in_place, {1, 2, 4, 8}, a }; - - assert (ou == ov); -*/ - } - - ///////////////////////////////// - { - typedef int T; - optional> ot {in_place}; - optional> ou {in_place, nullopt}; - optional> ov {optional{}}; - - (void) ot; - (void) ou; - - optional oi; - auto ooi = make_optional(oi); - static_assert( std::is_same>, decltype(ooi)>::value, ""); - } -} - - -bool fun(std::string , wpi::optional oi = wpi::nullopt) -{ - return bool(oi); -} - -TEST(Optional, example_converting_ctor) -{ - using namespace wpi; - - assert (true == fun("dog", 2)); - assert (false == fun("dog")); - assert (false == fun("dog", nullopt)); // just to be explicit -} - - -TEST(Optional, bad_comparison) -{ - tr2::optional oi, oj; - int i; - bool b = (oi == oj); - b = (oi >= i); - b = (oi == i); - unused(b); -} - - -//// NOT APPLICABLE ANYMORE -////TEST(Optional, perfect_ctor) -////{ -//// //tr2::optional ois = "OS"; -//// assert (*ois == "OS"); -//// -//// // FAILS: tr2::optional oes = "OS"; -//// tr2::optional oes{"OS"}; -//// assert (oes->s == "OS"); -////} - -TEST(Optional, value_or) -{ - tr2::optional oi = 1; - int i = oi.value_or(0); - assert (i == 1); - - oi = tr2::nullopt; - assert (oi.value_or(3) == 3); - - tr2::optional os{"AAA"}; - assert (os.value_or("BBB") == "AAA"); - os = {}; - assert (os.value_or("BBB") == "BBB"); -} - -TEST(Optional, reset) -{ - using namespace wpi; - optional oi {1}; - oi.reset(); - assert (!oi); - - int i = 1; - optional oir {i}; - oir.reset(); - assert (!oir); -} - -TEST(Optional, mixed_order) -{ - using namespace wpi; - - optional oN {nullopt}; - optional o0 {0}; - optional o1 {1}; - - assert ( (oN < 0)); - assert ( (oN < 1)); - assert (!(o0 < 0)); - assert ( (o0 < 1)); - assert (!(o1 < 0)); - assert (!(o1 < 1)); - - assert (!(oN >= 0)); - assert (!(oN >= 1)); - assert ( (o0 >= 0)); - assert (!(o0 >= 1)); - assert ( (o1 >= 0)); - assert ( (o1 >= 1)); - - assert (!(oN > 0)); - assert (!(oN > 1)); - assert (!(o0 > 0)); - assert (!(o0 > 1)); - assert ( (o1 > 0)); - assert (!(o1 > 1)); - - assert ( (oN <= 0)); - assert ( (oN <= 1)); - assert ( (o0 <= 0)); - assert ( (o0 <= 1)); - assert (!(o1 <= 0)); - assert ( (o1 <= 1)); - - assert ( (0 > oN)); - assert ( (1 > oN)); - assert (!(0 > o0)); - assert ( (1 > o0)); - assert (!(0 > o1)); - assert (!(1 > o1)); - - assert (!(0 <= oN)); - assert (!(1 <= oN)); - assert ( (0 <= o0)); - assert (!(1 <= o0)); - assert ( (0 <= o1)); - assert ( (1 <= o1)); - - assert (!(0 < oN)); - assert (!(1 < oN)); - assert (!(0 < o0)); - assert (!(1 < o0)); - assert ( (0 < o1)); - assert (!(1 < o1)); - - assert ( (0 >= oN)); - assert ( (1 >= oN)); - assert ( (0 >= o0)); - assert ( (1 >= o0)); - assert (!(0 >= o1)); - assert ( (1 >= o1)); -} - -struct BadRelops -{ - int i; -}; - -constexpr bool operator<(BadRelops a, BadRelops b) { return a.i < b.i; } -constexpr bool operator>(BadRelops a, BadRelops b) { return a.i < b.i; } // intentional error! - -TEST(Optional, bad_relops) -{ - using namespace wpi; - BadRelops a{1}, b{2}; - assert (a < b); - assert (a > b); - - optional oa = a, ob = b; - assert (oa < ob); - assert (!(oa > ob)); - - assert (oa < b); - assert (oa > b); - - optional ra = a, rb = b; - assert (ra < rb); - assert (!(ra > rb)); - - assert (ra < b); - assert (ra > b); -} - - -TEST(Optional, mixed_equality) -{ - using namespace wpi; - - assert (make_optional(0) == 0); - assert (make_optional(1) == 1); - assert (make_optional(0) != 1); - assert (make_optional(1) != 0); - - optional oN {nullopt}; - optional o0 {0}; - optional o1 {1}; - - assert (o0 == 0); - assert ( 0 == o0); - assert (o1 == 1); - assert ( 1 == o1); - assert (o1 != 0); - assert ( 0 != o1); - assert (o0 != 1); - assert ( 1 != o0); - - assert ( 1 != oN); - assert ( 0 != oN); - assert (oN != 1); - assert (oN != 0); - assert (!( 1 == oN)); - assert (!( 0 == oN)); - assert (!(oN == 1)); - assert (!(oN == 0)); - - std::string cat{"cat"}, dog{"dog"}; - optional oNil{}, oDog{"dog"}, oCat{"cat"}; - - assert (oCat == cat); - assert ( cat == oCat); - assert (oDog == dog); - assert ( dog == oDog); - assert (oDog != cat); - assert ( cat != oDog); - assert (oCat != dog); - assert ( dog != oCat); - - assert ( dog != oNil); - assert ( cat != oNil); - assert (oNil != dog); - assert (oNil != cat); - assert (!( dog == oNil)); - assert (!( cat == oNil)); - assert (!(oNil == dog)); - assert (!(oNil == cat)); -} - -TEST(Optional, const_propagation) -{ - using namespace wpi; - - optional mmi{0}; - static_assert(std::is_same::value, "WTF"); - - const optional cmi{0}; - static_assert(std::is_same::value, "WTF"); - - optional mci{0}; - static_assert(std::is_same::value, "WTF"); - - optional cci{0}; - static_assert(std::is_same::value, "WTF"); -} - - -static_assert(std::is_base_of::value, ""); - -TEST(Optional, safe_value) -{ - using namespace wpi; - - try { - optional ovN{}, ov1{1}; - - int& r1 = ov1.value(); - assert (r1 == 1); - - try { - ovN.value(); - assert (false); - } - catch (bad_optional_access const&) { - } - - { // ref variant - int i1 = 1; - optional orN{}, or1{i1}; - - int& r2 = or1.value(); - assert (r2 == 1); - - try { - orN.value(); - assert (false); - } - catch (bad_optional_access const&) { - } - } - } - catch(...) { - assert (false); - } -} - -TEST(Optional, optional_ref) -{ - using namespace tr2; - // FAILS: optional orr; - // FAILS: optional on; - int i = 8; - optional ori; - assert (!ori); - ori.emplace(i); - assert (bool(ori)); - assert (*ori == 8); - assert (&*ori == &i); - *ori = 9; - assert (i == 9); - - // FAILS: int& ir = ori.value_or(i); - int ii = ori.value_or(i); - assert (ii == 9); - ii = 7; - assert (*ori == 9); - - int j = 22; - auto&& oj = make_optional(std::ref(j)); - *oj = 23; - assert (&*oj == &j); - assert (j == 23); -} - -TEST(Optional, optional_ref_const_propagation) -{ - using namespace wpi; - - int i = 9; - const optional mi = i; - int& r = *mi; - optional ci = i; - static_assert(std::is_same::value, "WTF"); - static_assert(std::is_same::value, "WTF"); - - unused(r); -} - -TEST(Optional, optional_ref_assign) -{ - using namespace wpi; - - int i = 9; - optional ori = i; - - int j = 1; - ori = optional{j}; - ori = {j}; - // FAILS: ori = j; - - optional orx = ori; - ori = orx; - - optional orj = j; - - assert (ori); - assert (*ori == 1); - assert (ori == orj); - assert (i == 9); - - *ori = 2; - assert (*ori == 2); - assert (ori == 2); - assert (2 == ori); - assert (ori != 3); - - assert (ori == orj); - assert (j == 2); - assert (i == 9); - - ori = {}; - assert (!ori); - assert (ori != orj); - assert (j == 2); - assert (i == 9); -} - -TEST(Optional, optional_swap) -{ - namespace tr2 = wpi; - tr2::optional oi {1}, oj {}; - swap(oi, oj); - assert (oj); - assert (*oj == 1); - assert (!oi); - static_assert(noexcept(swap(oi, oj)), "swap() is not noexcept"); -} - - -TEST(Optional, optional_ref_swap) -{ - using namespace wpi; - int i = 0; - int j = 1; - optional oi = i; - optional oj = j; - - assert (&*oi == &i); - assert (&*oj == &j); - - swap(oi, oj); - assert (&*oi == &j); - assert (&*oj == &i); -} - -TEST(Optional, optional_initialization) -{ - using namespace tr2; - using std::string; - string s = "STR"; - - optional os{s}; - optional ot = s; - optional ou{"STR"}; - optional ov = string{"STR"}; - -} - -#include - -TEST(Optional, optional_hashing) -{ - using namespace tr2; - using std::string; - - std::hash hi; - std::hash> hoi; - std::hash hs; - std::hash> hos; - - assert (hi(0) == hoi(optional{0})); - assert (hi(1) == hoi(optional{1})); - assert (hi(3198) == hoi(optional{3198})); - - assert (hs("") == hos(optional{""})); - assert (hs("0") == hos(optional{"0"})); - assert (hs("Qa1#") == hos(optional{"Qa1#"})); - - std::unordered_set> set; - assert(set.find({"Qa1#"}) == set.end()); - - set.insert({"0"}); - assert(set.find({"Qa1#"}) == set.end()); - - set.insert({"Qa1#"}); - assert(set.find({"Qa1#"}) != set.end()); -} - - -// optional_ref_emulation -template -struct generic -{ - typedef T type; -}; - -template -struct generic -{ - typedef std::reference_wrapper type; -}; - -template -using Generic = typename generic::type; - -template -bool generic_fun() -{ - wpi::optional> op; - return bool(op); -} - -TEST(Optional, optional_ref_emulation) -{ - using namespace wpi; - optional> oi = 1; - assert (*oi == 1); - - int i = 8; - int j = 4; - optional> ori {i}; - assert (*ori == 8); - assert ((void*)&*ori != (void*)&i); // !DIFFERENT THAN optional - - *ori = j; - assert (*ori == 4); -} - - -TEST(Optional, moved_on_value_or) -{ - using namespace tr2; - optional oo{in_place}; - - assert (oo); - assert (oo->s == sDefaultConstructed); - - Oracle o = std::move(oo).value_or( Oracle{OracleVal{}} ); - assert (oo); - assert (oo->s == sMovedFrom); - assert (o.s == sMoveConstructed); - - optional> om {in_place, 1}; - assert (om); - assert (om->moved == false); - - /*MoveAware m =*/ std::move(om).value_or( MoveAware{1} ); - assert (om); - assert (om->moved == true); - -# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 - { - Date d = optional{in_place, 1}.value(); - assert (d.i); // to silence compiler warning - - Date d2 = *optional{in_place, 1}; - assert (d2.i); // to silence compiler warning - } -# endif -} - - -TEST(Optional, optional_ref_hashing) -{ - using namespace tr2; - using std::string; - - std::hash hi; - std::hash> hoi; - std::hash hs; - std::hash> hos; - - int i0 = 0; - int i1 = 1; - assert (hi(0) == hoi(optional{i0})); - assert (hi(1) == hoi(optional{i1})); - - string s{""}; - string s0{"0"}; - string sCAT{"CAT"}; - assert (hs("") == hos(optional{s})); - assert (hs("0") == hos(optional{s0})); - assert (hs("CAT") == hos(optional{sCAT})); - - std::unordered_set> set; - assert(set.find({sCAT}) == set.end()); - - set.insert({s0}); - assert(set.find({sCAT}) == set.end()); - - set.insert({sCAT}); - assert(set.find({sCAT}) != set.end()); -} - -struct Combined -{ - int m = 0; - int n = 1; - - constexpr Combined() : m{5}, n{6} {} - constexpr Combined(int m, int n) : m{m}, n{n} {} -}; - -struct Nasty -{ - int m = 0; - int n = 1; - - constexpr Nasty() : m{5}, n{6} {} - constexpr Nasty(int m, int n) : m{m}, n{n} {} - - int operator&() { return n; } - int operator&() const { return n; } -}; - -TEST(Optional, arrow_operator) -{ - using namespace wpi; - - optional oc1{in_place, 1, 2}; - assert (oc1); - assert (oc1->m == 1); - assert (oc1->n == 2); - - optional on{in_place, 1, 2}; - assert (on); - assert (on->m == 1); - assert (on->n == 2); -} - -TEST(Optional, arrow_wit_optional_ref) -{ - using namespace wpi; - - Combined c{1, 2}; - optional oc = c; - assert (oc); - assert (oc->m == 1); - assert (oc->n == 2); - - Nasty n{1, 2}; - Nasty m{3, 4}; - Nasty p{5, 6}; - - optional on{n}; - assert (on); - assert (on->m == 1); - assert (on->n == 2); - - on = {m}; - assert (on); - assert (on->m == 3); - assert (on->n == 4); - - on.emplace(p); - assert (on); - assert (on->m == 5); - assert (on->n == 6); - - optional om{in_place, n}; - assert (om); - assert (om->m == 1); - assert (om->n == 2); -} - -TEST(Optional, no_dangling_reference_in_value) -{ - // this mostly tests compiler warnings - using namespace wpi; - optional oi {2}; - unused (oi.value()); - const optional coi {3}; - unused (coi.value()); -} - -struct CountedObject -{ - static int _counter; - bool _throw; - CountedObject(bool b) : _throw(b) { ++_counter; } - CountedObject(CountedObject const& rhs) : _throw(rhs._throw) { if (_throw) throw int(); } - ~CountedObject() { --_counter; } -}; - -int CountedObject::_counter = 0; - -TEST(Optional, exception_safety) -{ - using namespace wpi; - try { - optional oo(in_place, true); // throw - optional o1(oo); - } - catch(...) - { - // - } - assert(CountedObject::_counter == 0); - - try { - optional oo(in_place, true); // throw - optional o1(std::move(oo)); // now move - } - catch(...) - { - // - } - assert(CountedObject::_counter == 0); -} - -TEST(Optional, nested_optional) -{ - using namespace wpi; - - optional>> o1 {nullopt}; - assert (!o1); - - optional>> o2 {in_place, nullopt}; - assert (o2); - assert (!*o2); - - optional>> o3 (in_place, in_place, nullopt); - assert (o3); - assert (*o3); - assert (!**o3); -} - -TEST(Optional, three_ways_of_having_value) -{ - using namespace wpi; - optional oN, o1 (1); - - assert (!oN); - assert (!oN.has_value()); - assert (oN == nullopt); - - assert (o1); - assert (o1.has_value()); - assert (o1 != nullopt); - - assert (bool(oN) == oN.has_value()); - assert (bool(o1) == o1.has_value()); - - int i = 1; - optional rN, r1 (i); - - assert (!rN); - assert (!rN.has_value()); - assert (rN == nullopt); - - assert (r1); - assert (r1.has_value()); - assert (r1 != nullopt); - - assert (bool(rN) == rN.has_value()); - assert (bool(r1) == r1.has_value()); -} - -//// constexpr tests - -// these 4 classes have different noexcept signatures in move operations -struct NothrowBoth { - NothrowBoth(NothrowBoth&&) noexcept(true) {}; - void operator=(NothrowBoth&&) noexcept(true) {}; -}; -struct NothrowCtor { - NothrowCtor(NothrowCtor&&) noexcept(true) {}; - void operator=(NothrowCtor&&) noexcept(false) {}; -}; -struct NothrowAssign { - NothrowAssign(NothrowAssign&&) noexcept(false) {}; - void operator=(NothrowAssign&&) noexcept(true) {}; -}; -struct NothrowNone { - NothrowNone(NothrowNone&&) noexcept(false) {}; - void operator=(NothrowNone&&) noexcept(false) {}; -}; - -void test_noexcept() -{ - { - tr2::optional b1, b2; - static_assert(noexcept(tr2::optional{tr2::constexpr_move(b1)}), "bad noexcept!"); - static_assert(noexcept(b1 = tr2::constexpr_move(b2)), "bad noexcept!"); - } - { - tr2::optional c1, c2; - static_assert(noexcept(tr2::optional{tr2::constexpr_move(c1)}), "bad noexcept!"); - static_assert(!noexcept(c1 = tr2::constexpr_move(c2)), "bad noexcept!"); - } - { - tr2::optional a1, a2; - static_assert(!noexcept(tr2::optional{tr2::constexpr_move(a1)}), "bad noexcept!"); - static_assert(!noexcept(a1 = tr2::constexpr_move(a2)), "bad noexcept!"); - } - { - tr2::optional n1, n2; - static_assert(!noexcept(tr2::optional{tr2::constexpr_move(n1)}), "bad noexcept!"); - static_assert(!noexcept(n1 = tr2::constexpr_move(n2)), "bad noexcept!"); - } -} - - -void constexpr_test_disengaged() -{ - constexpr tr2::optional g0{}; - constexpr tr2::optional g1{tr2::nullopt}; - static_assert( !g0, "initialized!" ); - static_assert( !g1, "initialized!" ); - - static_assert( bool(g1) == bool(g0), "ne!" ); - - static_assert( g1 == g0, "ne!" ); - static_assert( !(g1 != g0), "ne!" ); - static_assert( g1 >= g0, "ne!" ); - static_assert( !(g1 > g0), "ne!" ); - static_assert( g1 <= g0, "ne!" ); - static_assert( !(g1 = tr2::nullopt, "!" ); - static_assert( !(g1 > tr2::nullopt), "!" ); - - static_assert( (tr2::nullopt == g0), "!" ); - static_assert( !(tr2::nullopt != g0), "!" ); - static_assert( (tr2::nullopt >= g0), "!" ); - static_assert( !(tr2::nullopt > g0), "!" ); - static_assert( (tr2::nullopt <= g0), "!" ); - static_assert( !(tr2::nullopt < g0), "!" ); - - static_assert( (g1 != tr2::optional(1)), "!" ); - static_assert( !(g1 == tr2::optional(1)), "!" ); - static_assert( (g1 < tr2::optional(1)), "!" ); - static_assert( (g1 <= tr2::optional(1)), "!" ); - static_assert( !(g1 > tr2::optional(1)), "!" ); - static_assert( !(g1 > tr2::optional(1)), "!" ); -} - - -constexpr tr2::optional g0{}; -constexpr tr2::optional g2{2}; -static_assert( g2, "not initialized!" ); -static_assert( *g2 == 2, "not 2!" ); -static_assert( g2 == tr2::optional(2), "not 2!" ); -static_assert( g2 != g0, "eq!" ); - -# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 -static_assert( *tr2::optional{3} == 3, "WTF!" ); -static_assert( tr2::optional{3}.value() == 3, "WTF!" ); -static_assert( tr2::optional{3}.value_or(1) == 3, "WTF!" ); -static_assert( tr2::optional{}.value_or(4) == 4, "WTF!" ); -# endif - -constexpr tr2::optional gc0{tr2::in_place}; -static_assert(gc0->n == 6, "WTF!"); - -// optional refs -int gi = 0; -constexpr tr2::optional gori = gi; -constexpr tr2::optional gorn{}; -constexpr int& gri = *gori; -static_assert(gori, "WTF"); -static_assert(!gorn, "WTF"); -static_assert(gori != tr2::nullopt, "WTF"); -static_assert(gorn == tr2::nullopt, "WTF"); -static_assert(&gri == &*gori, "WTF"); - -constexpr int gci = 1; -constexpr tr2::optional gorci = gci; -constexpr tr2::optional gorcn{}; - -static_assert(gorcn < gorci, "WTF"); -static_assert(gorcn <= gorci, "WTF"); -static_assert(gorci == gorci, "WTF"); -static_assert(*gorci == 1, "WTF"); -static_assert(gorci == gci, "WTF"); - -namespace constexpr_optional_ref_and_arrow -{ - using namespace wpi; - constexpr Combined c{1, 2}; - constexpr optional oc = c; - static_assert(oc, "WTF!"); - static_assert(oc->m == 1, "WTF!"); - static_assert(oc->n == 2, "WTF!"); -} - -#if OPTIONAL_HAS_CONSTEXPR_INIT_LIST - -namespace InitList -{ - using namespace wpi; - - struct ConstInitLister - { - template - constexpr ConstInitLister(std::initializer_list il) : len (il.size()) {} - size_t len; - }; - - constexpr ConstInitLister CIL {2, 3, 4}; - static_assert(CIL.len == 3, "WTF!"); - - constexpr optional oil {in_place, {4, 5, 6, 7}}; - static_assert(oil, "WTF!"); - static_assert(oil->len == 4, "WTF!"); -} - -#endif // OPTIONAL_HAS_CONSTEXPR_INIT_LIST - -// end constexpr tests - - -#include - - -struct VEC -{ - std::vector v; - template - VEC( X&&...x) : v(std::forward(x)...) {} - - template - VEC(std::initializer_list il, X&&...x) : v(il, std::forward(x)...) {} -}; - - - -TEST(Optional, Vector) { - tr2::optional oi = 1; - assert (bool(oi)); - oi.operator=({}); - assert (!oi); - - VEC v = {5, 6}; - - if (OPTIONAL_HAS_CONSTEXPR_INIT_LIST) - std::cout << "Optional has constexpr initializer_list" << std::endl; - else - std::cout << "Optional doesn't have constexpr initializer_list" << std::endl; - - if (OPTIONAL_HAS_MOVE_ACCESSORS) - std::cout << "Optional has constexpr move accessors" << std::endl; - else - std::cout << "Optional doesn't have constexpr move accessors" << std::endl; -} -