Replace wpi::optional with C++17 std::optional (#1732)

Keep wpi/optional.h as a shim with deprecated warnings.
This commit is contained in:
Peter Johnson
2019-06-29 11:20:22 -07:00
committed by GitHub
parent 0fbb0d989e
commit 4b1b92bb74
11 changed files with 52 additions and 2490 deletions

View File

@@ -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
==============================================================================

View File

@@ -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/
}

View File

@@ -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<size_t> Width) {
std::optional<size_t> 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<size_t> Precision) {
std::optional<size_t> Precision) {
size_t Prec = Precision.value_or(getDefaultPrecision(Style));
if (std::isnan(N)) {

View File

@@ -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 <initializer_list>
#include <iterator>
#include <memory>
#include <optional>
#include <type_traits>
#include <vector>
@@ -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<T>() {}
/*implicit*/ MutableArrayRef(std::nullopt_t) : ArrayRef<T>() {}
/// Construct an MutableArrayRef from a single element.
/*implicit*/ MutableArrayRef(T &OneElt) : ArrayRef<T>(OneElt) {}

View File

@@ -29,6 +29,7 @@
#include <cassert>
#include <cstdint>
#include <cstdio>
#include <optional>
#include <tuple>
namespace wpi {
@@ -223,7 +224,7 @@ class FormattedBytes {
ArrayRef<uint8_t> Bytes;
// If not nullopt, display offsets for each line relative to starting value.
optional<uint64_t> FirstByteOffset;
std::optional<uint64_t> 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<uint8_t> B, uint32_t IL, optional<uint64_t> O,
FormattedBytes(ArrayRef<uint8_t> B, uint32_t IL, std::optional<uint64_t> 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<uint8_t> Bytes, optional<uint64_t> FirstByteOffset = nullopt,
format_bytes(ArrayRef<uint8_t> Bytes, std::optional<uint64_t> 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<uint8_t> Bytes, optional<uint64_t> FirstByteOffset = nullo
inline FormattedBytes
format_bytes_with_ascii(ArrayRef<uint8_t> Bytes,
optional<uint64_t> FirstByteOffset = nullopt,
std::optional<uint64_t> FirstByteOffset = std::nullopt,
uint32_t NumPerLine = 16, uint8_t ByteGroupSize = 4,
uint32_t IndentLevel = 0, bool Upper = false) {
return FormattedBytes(Bytes, IndentLevel, FirstByteOffset, NumPerLine,

View File

@@ -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 <cstdint>
#include <optional>
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<size_t> Width = nullopt);
std::optional<size_t> Width = std::nullopt);
void write_double(raw_ostream &S, double D, FloatStyle Style,
optional<size_t> Precision = nullopt);
std::optional<size_t> Precision = std::nullopt);
}
#endif

View File

@@ -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 <algorithm>
#include <cassert>
@@ -32,6 +31,7 @@
#include <iterator>
#include <limits>
#include <memory>
#include <optional>
#include <tuple>
#include <type_traits>
#include <utility>
@@ -595,16 +595,16 @@ static Iter next_or_end(const Iter &I, const Iter &End) {
template <typename Iter>
static auto deref_or_none(const Iter &I, const Iter &End)
-> wpi::optional<typename std::remove_const<
-> std::optional<typename std::remove_const<
typename std::remove_reference<decltype(*I)>::type>::type> {
if (I == End)
return nullopt;
return std::nullopt;
return *I;
}
template <typename Iter> struct ZipLongestItemType {
using type =
wpi::optional<typename std::remove_const<typename std::remove_reference<
std::optional<typename std::remove_const<typename std::remove_reference<
decltype(*std::declval<Iter>())>::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 <typename T, typename U, typename... Args>
detail::zip_longest_range<T, U, Args...> zip_longest(T &&t, U &&u,

View File

@@ -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 <cstddef>
#include <functional>
#include <optional>
#include <set>
#include <type_traits>
#include <utility>
@@ -178,16 +178,16 @@ public:
/// concept.
// FIXME: Add iterators that abstract over the small and large form, and then
// return those here.
std::pair<nullopt_t, bool> insert(const T &V) {
std::pair<std::nullopt_t, bool> 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 <typename IterT>

View File

@@ -16,8 +16,8 @@
#define WPIUTIL_WPI_VERSIONTUPLE_H
#include "wpi/StringRef.h"
#include "wpi/optional.h"
#include "wpi/raw_ostream.h"
#include <optional>
#include <string>
#include <tuple>
@@ -68,23 +68,23 @@ public:
unsigned getMajor() const { return Major; }
/// Retrieve the minor version number, if provided.
optional<unsigned> getMinor() const {
std::optional<unsigned> getMinor() const {
if (!HasMinor)
return nullopt;
return std::nullopt;
return Minor;
}
/// Retrieve the subminor version number, if provided.
optional<unsigned> getSubminor() const {
std::optional<unsigned> getSubminor() const {
if (!HasSubminor)
return nullopt;
return std::nullopt;
return Subminor;
}
/// Retrieve the build version number, if provided.
optional<unsigned> getBuild() const {
std::optional<unsigned> getBuild() const {
if (!HasBuild)
return nullopt;
return std::nullopt;
return Build;
}

View File

@@ -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 <utility>
# include <type_traits>
# include <initializer_list>
# include <cassert>
# include <functional>
# include <string>
# include <stdexcept>
# 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 T> class optional;
// 20.5.5, optional for lvalue reference types
template <class T> class optional<T&>;
// workaround: std utility functions aren't constexpr yet
template <class T> inline constexpr T&& constexpr_forward(typename std::remove_reference<T>::type& t) noexcept
{
return static_cast<T&&>(t);
}
template <class T> inline constexpr T&& constexpr_forward(typename std::remove_reference<T>::type&& t) noexcept
{
static_assert(!std::is_lvalue_reference<T>::value, "!!");
return static_cast<T&&>(t);
}
template <class T> inline constexpr typename std::remove_reference<T>::type&& constexpr_move(T&& t) noexcept
{
return static_cast<typename std::remove_reference<T>::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 <optional> instead")
#else
# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([]{assert(!#CHECK);}(), (EXPR)))
#warning "wpi/optional.h is deprecated; include <optional> instead"
#endif
#include <optional>
namespace detail_
{
namespace wpi {
// static_addressof: a constexpr version of addressof
template <typename T>
struct has_overloaded_addressof
{
template <class X>
constexpr static bool has_overload(...) { return false; }
using optional [[deprecated("use std::optional")]] = std::optional<T>;
template <class X, size_t S = sizeof(std::declval<X&>().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<T>(true);
};
[[deprecated("use std::nullopt")]] inline constexpr std::nullopt_t nullopt =
std::nullopt;
template <typename T, TR2_OPTIONAL_REQUIRES(!has_overloaded_addressof<T>)>
constexpr T* static_addressof(T& ref)
{
return &ref;
}
} // namespace wpi
template <typename T, TR2_OPTIONAL_REQUIRES(has_overloaded_addressof<T>)>
T* static_addressof(T& ref)
{
return std::addressof(ref);
}
// clang-format on
// the call to convert<A>(b) has return type A and converts b to type A iff b decltype(b) is implicitly convertible to A
template <class U>
constexpr U convert(U v) { return v; }
namespace swap_ns
{
using std::swap;
template <class T>
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 <class T>
union storage_t
{
unsigned char dummy_;
T value_;
constexpr storage_t( trivial_init_t ) noexcept : dummy_() {};
template <class... Args>
constexpr storage_t( Args&&... args ) : value_(constexpr_forward<Args>(args)...) {}
~storage_t(){}
};
template <class T>
union constexpr_storage_t
{
unsigned char dummy_;
T value_;
constexpr constexpr_storage_t( trivial_init_t ) noexcept : dummy_() {};
template <class... Args>
constexpr constexpr_storage_t( Args&&... args ) : value_(constexpr_forward<Args>(args)...) {}
~constexpr_storage_t() = default;
};
template <class T>
struct optional_base
{
bool init_;
storage_t<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 <class... Args> explicit optional_base(in_place_t, Args&&... args)
: init_(true), storage_(constexpr_forward<Args>(args)...) {}
template <class U, class... Args, TR2_OPTIONAL_REQUIRES(std::is_constructible<T, std::initializer_list<U>>)>
explicit optional_base(in_place_t, std::initializer_list<U> il, Args&&... args)
: init_(true), storage_(il, std::forward<Args>(args)...) {}
~optional_base() { if (init_) storage_.value_.T::~T(); }
};
template <class T>
struct constexpr_optional_base
{
bool init_;
constexpr_storage_t<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 <class... Args> explicit constexpr constexpr_optional_base(in_place_t, Args&&... args)
: init_(true), storage_(constexpr_forward<Args>(args)...) {}
template <class U, class... Args, TR2_OPTIONAL_REQUIRES(std::is_constructible<T, std::initializer_list<U>>)>
OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, std::initializer_list<U> il, Args&&... args)
: init_(true), storage_(il, std::forward<Args>(args)...) {}
~constexpr_optional_base() = default;
};
template <class T>
using OptionalBase = typename std::conditional<
std::is_trivially_destructible<T>::value, // if possible
constexpr_optional_base<typename std::remove_const<T>::type>, // use base with trivial destructor
optional_base<typename std::remove_const<T>::type>
>::type;
template <class T>
class optional : private OptionalBase<T>
{
static_assert( !std::is_same<typename std::decay<T>::type, nullopt_t>::value, "bad T" );
static_assert( !std::is_same<typename std::decay<T>::type, in_place_t>::value, "bad T" );
constexpr bool initialized() const noexcept { return OptionalBase<T>::init_; }
typename std::remove_const<T>::type* dataptr() { return std::addressof(OptionalBase<T>::storage_.value_); }
constexpr const T* dataptr() const { return detail_::static_addressof(OptionalBase<T>::storage_.value_); }
constexpr const T& contained_val() const& { return OptionalBase<T>::storage_.value_; }
# if OPTIONAL_HAS_MOVE_ACCESSORS == 1
constexpr T&& contained_val() && { return std::move(OptionalBase<T>::storage_.value_); }
constexpr T& contained_val() & { return OptionalBase<T>::storage_.value_; }
# else
T& contained_val() & { return OptionalBase<T>::storage_.value_; }
T&& contained_val() && { return std::move(OptionalBase<T>::storage_.value_); }
# endif
void clear() noexcept {
if (initialized()) dataptr()->T::~T();
OptionalBase<T>::init_ = false;
}
template <class... Args>
void initialize(Args&&... args) noexcept(noexcept(T(std::forward<Args>(args)...)))
{
assert(!OptionalBase<T>::init_);
::new (static_cast<void*>(dataptr())) T(std::forward<Args>(args)...);
OptionalBase<T>::init_ = true;
}
template <class U, class... Args>
void initialize(std::initializer_list<U> il, Args&&... args) noexcept(noexcept(T(il, std::forward<Args>(args)...)))
{
assert(!OptionalBase<T>::init_);
::new (static_cast<void*>(dataptr())) T(il, std::forward<Args>(args)...);
OptionalBase<T>::init_ = true;
}
public:
typedef T value_type;
// 20.5.5.1, constructors
constexpr optional() noexcept : OptionalBase<T>() {};
constexpr optional(nullopt_t) noexcept : OptionalBase<T>() {};
optional(const optional& rhs)
: OptionalBase<T>()
{
if (rhs.initialized()) {
::new (static_cast<void*>(dataptr())) T(*rhs);
OptionalBase<T>::init_ = true;
}
}
optional(optional&& rhs) noexcept(std::is_nothrow_move_constructible<T>::value)
: OptionalBase<T>()
{
if (rhs.initialized()) {
::new (static_cast<void*>(dataptr())) T(std::move(*rhs));
OptionalBase<T>::init_ = true;
}
}
constexpr optional(const T& v) : OptionalBase<T>(v) {}
constexpr optional(T&& v) : OptionalBase<T>(constexpr_move(v)) {}
template <class... Args>
explicit constexpr optional(in_place_t, Args&&... args)
: OptionalBase<T>(in_place_t{}, constexpr_forward<Args>(args)...) {}
template <class U, class... Args, TR2_OPTIONAL_REQUIRES(std::is_constructible<T, std::initializer_list<U>>)>
OPTIONAL_CONSTEXPR_INIT_LIST explicit optional(in_place_t, std::initializer_list<U> il, Args&&... args)
: OptionalBase<T>(in_place_t{}, il, constexpr_forward<Args>(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<T>::value && std::is_nothrow_move_constructible<T>::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 <class U>
auto operator=(U&& v)
-> typename std::enable_if
<
std::is_same<typename std::decay<U>::type, T>::value,
optional&
>::type
{
if (initialized()) { contained_val() = std::forward<U>(v); }
else { initialize(std::forward<U>(v)); }
return *this;
}
template <class... Args>
void emplace(Args&&... args)
{
clear();
initialize(std::forward<Args>(args)...);
}
template <class U, class... Args>
void emplace(std::initializer_list<U> il, Args&&... args)
{
clear();
initialize<U, Args...>(il, std::forward<Args>(args)...);
}
// 20.5.4.4, Swap
void swap(optional<T>& rhs) noexcept(std::is_nothrow_move_constructible<T>::value
&& noexcept(detail_::swap_ns::adl_swap(std::declval<T&>(), std::declval<T&>())))
{
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 <class V>
constexpr T value_or(V&& v) const&
{
return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v));
}
# if OPTIONAL_HAS_MOVE_ACCESSORS == 1
template <class V>
constexpr T value_or(V&& v) &&
{
return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v));
}
# else
template <class V>
T value_or(V&& v) &&
{
return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v));
}
# endif
// 20.6.3.6, modifiers
void reset() noexcept { clear(); }
};
template <class T>
class optional<T&>
{
static_assert( !std::is_same<T, nullopt_t>::value, "bad T" );
static_assert( !std::is_same<T, in_place_t>::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 <typename U>
auto operator=(U&& rhs) noexcept
-> typename std::enable_if
<
std::is_same<typename std::decay<U>::type, optional<T&>>::value,
optional&
>::type
{
ref = rhs.ref;
return *this;
}
template <typename U>
auto operator=(U&& rhs) noexcept
-> typename std::enable_if
<
!std::is_same<typename std::decay<U>::type, optional<T&>>::value,
optional&
>::type
= delete;
void emplace(T& v) noexcept {
ref = detail_::static_addressof(v);
}
void emplace(T&&) = delete;
void swap(optional<T&>& 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 <class V>
constexpr typename std::decay<T>::type value_or(V&& v) const
{
return *this ? **this : detail_::convert<typename std::decay<T>::type>(constexpr_forward<V>(v));
}
// x.x.x.x, modifiers
void reset() noexcept { ref = nullptr; }
};
template <class T>
class optional<T&&>
{
static_assert( sizeof(T) == 0, "optional rvalue references disallowed" );
};
// 20.5.8, Relational operators
template <class T> constexpr bool operator==(const optional<T>& x, const optional<T>& y)
{
return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y;
}
template <class T> constexpr bool operator!=(const optional<T>& x, const optional<T>& y)
{
return !(x == y);
}
template <class T> constexpr bool operator<(const optional<T>& x, const optional<T>& y)
{
return (!y) ? false : (!x) ? true : *x < *y;
}
template <class T> constexpr bool operator>(const optional<T>& x, const optional<T>& y)
{
return (y < x);
}
template <class T> constexpr bool operator<=(const optional<T>& x, const optional<T>& y)
{
return !(y < x);
}
template <class T> constexpr bool operator>=(const optional<T>& x, const optional<T>& y)
{
return !(x < y);
}
// 20.5.9, Comparison with nullopt
template <class T> constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept
{
return (!x);
}
template <class T> constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept
{
return (!x);
}
template <class T> constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept
{
return bool(x);
}
template <class T> constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept
{
return bool(x);
}
template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept
{
return false;
}
template <class T> constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept
{
return bool(x);
}
template <class T> constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept
{
return (!x);
}
template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept
{
return true;
}
template <class T> constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept
{
return bool(x);
}
template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept
{
return false;
}
template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept
{
return true;
}
template <class T> constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept
{
return (!x);
}
// 20.5.10, Comparison with T
template <class T> constexpr bool operator==(const optional<T>& x, const T& v)
{
return bool(x) ? *x == v : false;
}
template <class T> constexpr bool operator==(const T& v, const optional<T>& x)
{
return bool(x) ? v == *x : false;
}
template <class T> constexpr bool operator!=(const optional<T>& x, const T& v)
{
return bool(x) ? *x != v : true;
}
template <class T> constexpr bool operator!=(const T& v, const optional<T>& x)
{
return bool(x) ? v != *x : true;
}
template <class T> constexpr bool operator<(const optional<T>& x, const T& v)
{
return bool(x) ? *x < v : true;
}
template <class T> constexpr bool operator>(const T& v, const optional<T>& x)
{
return bool(x) ? v > *x : true;
}
template <class T> constexpr bool operator>(const optional<T>& x, const T& v)
{
return bool(x) ? *x > v : false;
}
template <class T> constexpr bool operator<(const T& v, const optional<T>& x)
{
return bool(x) ? v < *x : false;
}
template <class T> constexpr bool operator>=(const optional<T>& x, const T& v)
{
return bool(x) ? *x >= v : false;
}
template <class T> constexpr bool operator<=(const T& v, const optional<T>& x)
{
return bool(x) ? v <= *x : false;
}
template <class T> constexpr bool operator<=(const optional<T>& x, const T& v)
{
return bool(x) ? *x <= v : true;
}
template <class T> constexpr bool operator>=(const T& v, const optional<T>& x)
{
return bool(x) ? v >= *x : true;
}
// Comparison of optional<T&> with T
template <class T> constexpr bool operator==(const optional<T&>& x, const T& v)
{
return bool(x) ? *x == v : false;
}
template <class T> constexpr bool operator==(const T& v, const optional<T&>& x)
{
return bool(x) ? v == *x : false;
}
template <class T> constexpr bool operator!=(const optional<T&>& x, const T& v)
{
return bool(x) ? *x != v : true;
}
template <class T> constexpr bool operator!=(const T& v, const optional<T&>& x)
{
return bool(x) ? v != *x : true;
}
template <class T> constexpr bool operator<(const optional<T&>& x, const T& v)
{
return bool(x) ? *x < v : true;
}
template <class T> constexpr bool operator>(const T& v, const optional<T&>& x)
{
return bool(x) ? v > *x : true;
}
template <class T> constexpr bool operator>(const optional<T&>& x, const T& v)
{
return bool(x) ? *x > v : false;
}
template <class T> constexpr bool operator<(const T& v, const optional<T&>& x)
{
return bool(x) ? v < *x : false;
}
template <class T> constexpr bool operator>=(const optional<T&>& x, const T& v)
{
return bool(x) ? *x >= v : false;
}
template <class T> constexpr bool operator<=(const T& v, const optional<T&>& x)
{
return bool(x) ? v <= *x : false;
}
template <class T> constexpr bool operator<=(const optional<T&>& x, const T& v)
{
return bool(x) ? *x <= v : true;
}
template <class T> constexpr bool operator>=(const T& v, const optional<T&>& x)
{
return bool(x) ? v >= *x : true;
}
// Comparison of optional<T const&> with T
template <class T> constexpr bool operator==(const optional<const T&>& x, const T& v)
{
return bool(x) ? *x == v : false;
}
template <class T> constexpr bool operator==(const T& v, const optional<const T&>& x)
{
return bool(x) ? v == *x : false;
}
template <class T> constexpr bool operator!=(const optional<const T&>& x, const T& v)
{
return bool(x) ? *x != v : true;
}
template <class T> constexpr bool operator!=(const T& v, const optional<const T&>& x)
{
return bool(x) ? v != *x : true;
}
template <class T> constexpr bool operator<(const optional<const T&>& x, const T& v)
{
return bool(x) ? *x < v : true;
}
template <class T> constexpr bool operator>(const T& v, const optional<const T&>& x)
{
return bool(x) ? v > *x : true;
}
template <class T> constexpr bool operator>(const optional<const T&>& x, const T& v)
{
return bool(x) ? *x > v : false;
}
template <class T> constexpr bool operator<(const T& v, const optional<const T&>& x)
{
return bool(x) ? v < *x : false;
}
template <class T> constexpr bool operator>=(const optional<const T&>& x, const T& v)
{
return bool(x) ? *x >= v : false;
}
template <class T> constexpr bool operator<=(const T& v, const optional<const T&>& x)
{
return bool(x) ? v <= *x : false;
}
template <class T> constexpr bool operator<=(const optional<const T&>& x, const T& v)
{
return bool(x) ? *x <= v : true;
}
template <class T> constexpr bool operator>=(const T& v, const optional<const T&>& x)
{
return bool(x) ? v >= *x : true;
}
// 20.5.12, Specialized algorithms
template <class T>
void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y)))
{
x.swap(y);
}
template <class T>
constexpr optional<typename std::decay<T>::type> make_optional(T&& v)
{
return optional<typename std::decay<T>::type>(constexpr_forward<T>(v));
}
template <class X>
constexpr optional<X&> make_optional(std::reference_wrapper<X> v)
{
return optional<X&>(v.get());
}
} // namespace wpi
namespace std
{
template <typename T>
struct hash<wpi::optional<T>>
{
typedef typename hash<T>::result_type result_type;
typedef wpi::optional<T> argument_type;
constexpr result_type operator()(argument_type const& arg) const {
return arg ? std::hash<T>{}(*arg) : result_type{};
}
};
template <typename T>
struct hash<wpi::optional<T&>>
{
typedef typename hash<T>::result_type result_type;
typedef wpi::optional<T&> argument_type;
constexpr result_type operator()(argument_type const& arg) const {
return arg ? std::hash<T>{}(*arg) : result_type{};
}
};
}
# undef TR2_OPTIONAL_REQUIRES
# undef TR2_OPTIONAL_ASSERTED_EXPRESSION
# endif //WPIUTIL_WPI_OPTIONAL_H
#endif // WPIUTIL_WPI_OPTIONAL_H_

File diff suppressed because it is too large Load Diff