Cross-port the latest resolution of LWG2756 and some bug-fixes to experimental::optional.
Cross-port the latest resolution of LWG2756 and some bug-fixes to experimental::optional. PR libstdc++/77288 PR libstdc++/77727 * include/experimental/optional (_Optional_base): Remove constructors that take a _Tp. (__is_optional_impl, __is_optional): Remove. (__converts_from_optional): New. (optional(_Up&&)): Fix constraints, call base with in_place. (optional(const optional<_Up>&)): Fix constraints, use emplace. (optional(optional<_Up>&&)): Likewise. (operator=(_Up&&)): Fix constraints. (operator=(const optional<_Up>&)): Likewise. (operator=(optional<_Up>&&)): Likewise. (emplace(_Args&&...)): Constrain. (emplace(initializer_list<_Up>, _Args&&...)): Likewise. * testsuite/experimental/optional/77288.cc: New. * testsuite/experimental/optional/assignment/5.cc: Adjust. * testsuite/experimental/optional/cons/77727.cc: New. * testsuite/experimental/optional/cons/value.cc: Adjust. From-SVN: r241476
This commit is contained in:
parent
405def8d46
commit
f11cc05023
|
@ -1,3 +1,26 @@
|
||||||
|
2016-10-24 Ville Voutilainen <ville.voutilainen@gmail.com>
|
||||||
|
|
||||||
|
Cross-port the latest resolution of LWG2756 and some
|
||||||
|
bug-fixes to experimental::optional.
|
||||||
|
PR libstdc++/77288
|
||||||
|
PR libstdc++/77727
|
||||||
|
* include/experimental/optional (_Optional_base):
|
||||||
|
Remove constructors that take a _Tp.
|
||||||
|
(__is_optional_impl, __is_optional): Remove.
|
||||||
|
(__converts_from_optional): New.
|
||||||
|
(optional(_Up&&)): Fix constraints, call base with in_place.
|
||||||
|
(optional(const optional<_Up>&)): Fix constraints, use emplace.
|
||||||
|
(optional(optional<_Up>&&)): Likewise.
|
||||||
|
(operator=(_Up&&)): Fix constraints.
|
||||||
|
(operator=(const optional<_Up>&)): Likewise.
|
||||||
|
(operator=(optional<_Up>&&)): Likewise.
|
||||||
|
(emplace(_Args&&...)): Constrain.
|
||||||
|
(emplace(initializer_list<_Up>, _Args&&...)): Likewise.
|
||||||
|
* testsuite/experimental/optional/77288.cc: New.
|
||||||
|
* testsuite/experimental/optional/assignment/5.cc: Adjust.
|
||||||
|
* testsuite/experimental/optional/cons/77727.cc: New.
|
||||||
|
* testsuite/experimental/optional/cons/value.cc: Adjust.
|
||||||
|
|
||||||
2016-10-24 Jonathan Wakely <jwakely@redhat.com>
|
2016-10-24 Jonathan Wakely <jwakely@redhat.com>
|
||||||
|
|
||||||
* include/bits/stl_vector.h (vector::_M_data_ptr, vector::data):
|
* include/bits/stl_vector.h (vector::_M_data_ptr, vector::data):
|
||||||
|
|
|
@ -214,12 +214,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
: _Optional_base{} { }
|
: _Optional_base{} { }
|
||||||
|
|
||||||
// Constructors for engaged optionals.
|
// Constructors for engaged optionals.
|
||||||
constexpr _Optional_base(const _Tp& __t)
|
|
||||||
: _M_payload(__t), _M_engaged(true) { }
|
|
||||||
|
|
||||||
constexpr _Optional_base(_Tp&& __t)
|
|
||||||
: _M_payload(std::move(__t)), _M_engaged(true) { }
|
|
||||||
|
|
||||||
template<typename... _Args>
|
template<typename... _Args>
|
||||||
constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
|
constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
|
||||||
: _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
|
: _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
|
||||||
|
@ -356,12 +350,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
constexpr _Optional_base(nullopt_t) noexcept
|
constexpr _Optional_base(nullopt_t) noexcept
|
||||||
: _Optional_base{} { }
|
: _Optional_base{} { }
|
||||||
|
|
||||||
constexpr _Optional_base(const _Tp& __t)
|
|
||||||
: _M_payload(__t), _M_engaged(true) { }
|
|
||||||
|
|
||||||
constexpr _Optional_base(_Tp&& __t)
|
|
||||||
: _M_payload(std::move(__t)), _M_engaged(true) { }
|
|
||||||
|
|
||||||
template<typename... _Args>
|
template<typename... _Args>
|
||||||
constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
|
constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
|
||||||
: _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
|
: _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
|
||||||
|
@ -474,19 +462,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
template<typename _Tp>
|
template<typename _Tp>
|
||||||
class optional;
|
class optional;
|
||||||
|
|
||||||
template<typename>
|
template<typename _Tp, typename _Up>
|
||||||
struct __is_optional_impl : false_type
|
using __converts_from_optional =
|
||||||
{ };
|
__or_<is_constructible<_Tp, const optional<_Up>&>,
|
||||||
|
is_constructible<_Tp, optional<_Up>&>,
|
||||||
template<typename _Tp>
|
is_constructible<_Tp, const optional<_Up>&&>,
|
||||||
struct __is_optional_impl<optional<_Tp>> : true_type
|
is_constructible<_Tp, optional<_Up>&&>,
|
||||||
{ };
|
is_convertible<const optional<_Up>&, _Tp>,
|
||||||
|
is_convertible<optional<_Up>&, _Tp>,
|
||||||
template<typename _Tp>
|
is_convertible<const optional<_Up>&&, _Tp>,
|
||||||
struct __is_optional
|
is_convertible<optional<_Up>&&, _Tp>>;
|
||||||
: public __is_optional_impl<std::remove_cv_t<std::remove_reference_t<_Tp>>>
|
|
||||||
{ };
|
|
||||||
|
|
||||||
|
template<typename _Tp, typename _Up>
|
||||||
|
using __assigns_from_optional =
|
||||||
|
__or_<is_assignable<_Tp&, const optional<_Up>&>,
|
||||||
|
is_assignable<_Tp&, optional<_Up>&>,
|
||||||
|
is_assignable<_Tp&, const optional<_Up>&&>,
|
||||||
|
is_assignable<_Tp&, optional<_Up>&&>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Class template for optional values.
|
* @brief Class template for optional values.
|
||||||
|
@ -522,75 +514,75 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
|
|
||||||
constexpr optional() = default;
|
constexpr optional() = default;
|
||||||
// Converting constructors for engaged optionals.
|
// Converting constructors for engaged optionals.
|
||||||
template <typename _Up,
|
template <typename _Up = _Tp,
|
||||||
enable_if_t<__and_<
|
enable_if_t<__and_<
|
||||||
__not_<is_same<_Tp, _Up>>,
|
__not_<is_same<optional<_Tp>, decay_t<_Up>>>,
|
||||||
is_constructible<_Tp, _Up&&>,
|
is_constructible<_Tp, _Up&&>,
|
||||||
is_convertible<_Up&&, _Tp>
|
is_convertible<_Up&&, _Tp>
|
||||||
>::value, bool> = true>
|
>::value, bool> = true>
|
||||||
constexpr optional(_Up&& __t)
|
constexpr optional(_Up&& __t)
|
||||||
: _Base(_Tp(std::forward<_Up>(__t))) { }
|
: _Base(in_place, std::forward<_Up>(__t)) { }
|
||||||
|
|
||||||
template <typename _Up,
|
template <typename _Up = _Tp,
|
||||||
enable_if_t<__and_<
|
enable_if_t<__and_<
|
||||||
__not_<is_same<_Tp, _Up>>,
|
__not_<is_same<optional<_Tp>, decay_t<_Up>>>,
|
||||||
is_constructible<_Tp, _Up&&>,
|
is_constructible<_Tp, _Up&&>,
|
||||||
__not_<is_convertible<_Up&&, _Tp>>
|
__not_<is_convertible<_Up&&, _Tp>>
|
||||||
>::value, bool> = false>
|
>::value, bool> = false>
|
||||||
explicit constexpr optional(_Up&& __t)
|
explicit constexpr optional(_Up&& __t)
|
||||||
: _Base(_Tp(std::forward<_Up>(__t))) { }
|
: _Base(in_place, std::forward<_Up>(__t)) { }
|
||||||
|
|
||||||
template <typename _Up,
|
template <typename _Up,
|
||||||
enable_if_t<__and_<
|
enable_if_t<__and_<
|
||||||
__not_<is_same<_Tp, _Up>>,
|
__not_<is_same<_Tp, _Up>>,
|
||||||
__not_<is_constructible<
|
|
||||||
_Tp, const optional<_Up>&>>,
|
|
||||||
__not_<is_convertible<
|
|
||||||
const optional<_Up>&, _Tp>>,
|
|
||||||
is_constructible<_Tp, const _Up&>,
|
is_constructible<_Tp, const _Up&>,
|
||||||
is_convertible<const _Up&, _Tp>
|
is_convertible<const _Up&, _Tp>,
|
||||||
|
__not_<__converts_from_optional<_Tp, _Up>>
|
||||||
>::value, bool> = true>
|
>::value, bool> = true>
|
||||||
constexpr optional(const optional<_Up>& __t)
|
constexpr optional(const optional<_Up>& __t)
|
||||||
: _Base(__t ? optional<_Tp>(*__t) : optional<_Tp>()) { }
|
{
|
||||||
|
if (__t)
|
||||||
|
emplace(*__t);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename _Up,
|
template <typename _Up,
|
||||||
enable_if_t<__and_<
|
enable_if_t<__and_<
|
||||||
__not_<is_same<_Tp, _Up>>,
|
__not_<is_same<_Tp, _Up>>,
|
||||||
__not_<is_constructible<
|
|
||||||
_Tp, const optional<_Up>&>>,
|
|
||||||
__not_<is_convertible<
|
|
||||||
const optional<_Up>&, _Tp>>,
|
|
||||||
is_constructible<_Tp, const _Up&>,
|
is_constructible<_Tp, const _Up&>,
|
||||||
__not_<is_convertible<const _Up&, _Tp>>
|
__not_<is_convertible<const _Up&, _Tp>>,
|
||||||
|
__not_<__converts_from_optional<_Tp, _Up>>
|
||||||
>::value, bool> = false>
|
>::value, bool> = false>
|
||||||
explicit constexpr optional(const optional<_Up>& __t)
|
explicit constexpr optional(const optional<_Up>& __t)
|
||||||
: _Base(__t ? optional<_Tp>(*__t) : optional<_Tp>()) { }
|
{
|
||||||
|
if (__t)
|
||||||
|
emplace(*__t);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename _Up,
|
template <typename _Up,
|
||||||
enable_if_t<__and_<
|
enable_if_t<__and_<
|
||||||
__not_<is_same<_Tp, _Up>>,
|
__not_<is_same<_Tp, _Up>>,
|
||||||
__not_<is_constructible<
|
|
||||||
_Tp, optional<_Up>&&>>,
|
|
||||||
__not_<is_convertible<
|
|
||||||
optional<_Up>&&, _Tp>>,
|
|
||||||
is_constructible<_Tp, _Up&&>,
|
is_constructible<_Tp, _Up&&>,
|
||||||
is_convertible<_Up&&, _Tp>
|
is_convertible<_Up&&, _Tp>,
|
||||||
|
__not_<__converts_from_optional<_Tp, _Up>>
|
||||||
>::value, bool> = true>
|
>::value, bool> = true>
|
||||||
constexpr optional(optional<_Up>&& __t)
|
constexpr optional(optional<_Up>&& __t)
|
||||||
: _Base(__t ? optional<_Tp>(std::move(*__t)) : optional<_Tp>()) { }
|
{
|
||||||
|
if (__t)
|
||||||
|
emplace(std::move(*__t));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename _Up,
|
template <typename _Up,
|
||||||
enable_if_t<__and_<
|
enable_if_t<__and_<
|
||||||
__not_<is_same<_Tp, _Up>>,
|
__not_<is_same<_Tp, _Up>>,
|
||||||
__not_<is_constructible<
|
|
||||||
_Tp, optional<_Up>&&>>,
|
|
||||||
__not_<is_convertible<
|
|
||||||
optional<_Up>&&, _Tp>>,
|
|
||||||
is_constructible<_Tp, _Up&&>,
|
is_constructible<_Tp, _Up&&>,
|
||||||
__not_<is_convertible<_Up&&, _Tp>>
|
__not_<is_convertible<_Up&&, _Tp>>,
|
||||||
|
__not_<__converts_from_optional<_Tp, _Up>>
|
||||||
>::value, bool> = false>
|
>::value, bool> = false>
|
||||||
explicit constexpr optional(optional<_Up>&& __t)
|
explicit constexpr optional(optional<_Up>&& __t)
|
||||||
: _Base(__t ? optional<_Tp>(std::move(*__t)) : optional<_Tp>()) { }
|
{
|
||||||
|
if (__t)
|
||||||
|
emplace(std::move(*__t));
|
||||||
|
}
|
||||||
|
|
||||||
// [X.Y.4.3] (partly) Assignment.
|
// [X.Y.4.3] (partly) Assignment.
|
||||||
optional&
|
optional&
|
||||||
|
@ -600,18 +592,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename _Up,
|
template<typename _Up = _Tp>
|
||||||
enable_if_t<__and_<
|
enable_if_t<__and_<
|
||||||
__not_<is_same<_Up, nullopt_t>>,
|
__not_<is_same<optional<_Tp>, decay_t<_Up>>>,
|
||||||
__not_<__is_optional<_Up>>>::value,
|
is_constructible<_Tp, _Up>,
|
||||||
bool> = true>
|
__not_<__and_<is_scalar<_Tp>,
|
||||||
optional&
|
is_same<_Tp, decay_t<_Up>>>>,
|
||||||
|
is_assignable<_Tp&, _Up>>::value,
|
||||||
|
optional&>
|
||||||
operator=(_Up&& __u)
|
operator=(_Up&& __u)
|
||||||
{
|
{
|
||||||
static_assert(__and_<is_constructible<_Tp, _Up>,
|
|
||||||
is_assignable<_Tp&, _Up>>(),
|
|
||||||
"Cannot assign to value type from argument");
|
|
||||||
|
|
||||||
if (this->_M_is_engaged())
|
if (this->_M_is_engaged())
|
||||||
this->_M_get() = std::forward<_Up>(__u);
|
this->_M_get() = std::forward<_Up>(__u);
|
||||||
else
|
else
|
||||||
|
@ -620,17 +610,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename _Up,
|
template<typename _Up>
|
||||||
enable_if_t<__and_<
|
enable_if_t<__and_<
|
||||||
__not_<is_same<_Tp, _Up>>>::value,
|
__not_<is_same<_Tp, _Up>>,
|
||||||
bool> = true>
|
is_constructible<_Tp, const _Up&>,
|
||||||
optional&
|
is_assignable<_Tp&, _Up>,
|
||||||
|
__not_<__converts_from_optional<_Tp, _Up>>,
|
||||||
|
__not_<__assigns_from_optional<_Tp, _Up>>
|
||||||
|
>::value,
|
||||||
|
optional&>
|
||||||
operator=(const optional<_Up>& __u)
|
operator=(const optional<_Up>& __u)
|
||||||
{
|
{
|
||||||
static_assert(__and_<is_constructible<_Tp, _Up>,
|
|
||||||
is_assignable<_Tp&, _Up>>(),
|
|
||||||
"Cannot assign to value type from argument");
|
|
||||||
|
|
||||||
if (__u)
|
if (__u)
|
||||||
{
|
{
|
||||||
if (this->_M_is_engaged())
|
if (this->_M_is_engaged())
|
||||||
|
@ -645,17 +635,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename _Up,
|
template<typename _Up>
|
||||||
enable_if_t<__and_<
|
enable_if_t<__and_<
|
||||||
__not_<is_same<_Tp, _Up>>>::value,
|
__not_<is_same<_Tp, _Up>>,
|
||||||
bool> = true>
|
is_constructible<_Tp, _Up>,
|
||||||
optional&
|
is_assignable<_Tp&, _Up>,
|
||||||
|
__not_<__converts_from_optional<_Tp, _Up>>,
|
||||||
|
__not_<__assigns_from_optional<_Tp, _Up>>
|
||||||
|
>::value,
|
||||||
|
optional&>
|
||||||
operator=(optional<_Up>&& __u)
|
operator=(optional<_Up>&& __u)
|
||||||
{
|
{
|
||||||
static_assert(__and_<is_constructible<_Tp, _Up>,
|
|
||||||
is_assignable<_Tp&, _Up>>(),
|
|
||||||
"Cannot assign to value type from argument");
|
|
||||||
|
|
||||||
if (__u)
|
if (__u)
|
||||||
{
|
{
|
||||||
if (this->_M_is_engaged())
|
if (this->_M_is_engaged())
|
||||||
|
@ -672,18 +662,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... _Args>
|
template<typename... _Args>
|
||||||
void
|
enable_if_t<is_constructible<_Tp, _Args&&...>::value>
|
||||||
emplace(_Args&&... __args)
|
emplace(_Args&&... __args)
|
||||||
{
|
{
|
||||||
static_assert(is_constructible<_Tp, _Args&&...>(),
|
|
||||||
"Cannot emplace value type from arguments");
|
|
||||||
|
|
||||||
this->_M_reset();
|
this->_M_reset();
|
||||||
this->_M_construct(std::forward<_Args>(__args)...);
|
this->_M_construct(std::forward<_Args>(__args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename _Up, typename... _Args>
|
template<typename _Up, typename... _Args>
|
||||||
enable_if_t<is_constructible<_Tp, initializer_list<_Up>&,
|
enable_if_t<is_constructible<_Tp, initializer_list<_Up>&,
|
||||||
_Args&&...>::value>
|
_Args&&...>::value>
|
||||||
emplace(initializer_list<_Up> __il, _Args&&... __args)
|
emplace(initializer_list<_Up> __il, _Args&&... __args)
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,405 @@
|
||||||
|
// { dg-do run { target c++14 } }
|
||||||
|
|
||||||
|
// Copyright (C) 2016 Free Software Foundation, Inc.
|
||||||
|
//
|
||||||
|
// This file is part of the GNU ISO C++ Library. This library is free
|
||||||
|
// software; you can redistribute it and/or modify it under the
|
||||||
|
// terms of the GNU General Public License as published by the
|
||||||
|
// Free Software Foundation; either version 3, or (at your option)
|
||||||
|
// any later version.
|
||||||
|
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a moved_to of the GNU General Public License along
|
||||||
|
// with this library; see the file COPYING3. If not see
|
||||||
|
// <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include <experimental/optional>
|
||||||
|
#include <experimental/any>
|
||||||
|
|
||||||
|
using std::experimental::optional;
|
||||||
|
|
||||||
|
#include <testsuite_hooks.h>
|
||||||
|
|
||||||
|
void test01()
|
||||||
|
{
|
||||||
|
optional<optional<int>> nested_element;
|
||||||
|
optional<int> element = {};
|
||||||
|
nested_element = element;
|
||||||
|
VERIFY(nested_element);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct service_result
|
||||||
|
{
|
||||||
|
static optional<T> get_result()
|
||||||
|
{
|
||||||
|
T sr;
|
||||||
|
return sr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static optional<T> get_result_with_cond(bool cond)
|
||||||
|
{
|
||||||
|
if (cond)
|
||||||
|
return T{};
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void test02()
|
||||||
|
{
|
||||||
|
VERIFY(service_result<int>::get_result());
|
||||||
|
VERIFY(service_result<optional<int>>::get_result());
|
||||||
|
VERIFY(service_result<int>::get_result_with_cond(true));
|
||||||
|
VERIFY(service_result<optional<int>>::get_result_with_cond(true));
|
||||||
|
VERIFY(!service_result<int>::get_result_with_cond(false));
|
||||||
|
VERIFY(!service_result<optional<int>>::get_result_with_cond(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Widget
|
||||||
|
{
|
||||||
|
Widget(int) {}
|
||||||
|
Widget(optional<int>) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void test03()
|
||||||
|
{
|
||||||
|
optional<Widget> w;
|
||||||
|
w = optional<int>();
|
||||||
|
VERIFY(w);
|
||||||
|
static_assert(!std::is_assignable<optional<Widget>&,
|
||||||
|
optional<short>>::value);
|
||||||
|
w = optional<optional<int>>();
|
||||||
|
VERIFY(!w);
|
||||||
|
static_assert(!std::is_assignable<optional<Widget>&,
|
||||||
|
optional<optional<short>>>::value);
|
||||||
|
|
||||||
|
optional<Widget> w2{optional<int>()};
|
||||||
|
VERIFY(w2);
|
||||||
|
optional<Widget> w3 = optional<int>();
|
||||||
|
VERIFY(w3);
|
||||||
|
optional<Widget> w4{optional<short>()};
|
||||||
|
VERIFY(w4);
|
||||||
|
static_assert(!std::is_convertible<optional<short>&&,
|
||||||
|
optional<Widget>>::value);
|
||||||
|
|
||||||
|
optional<Widget> w6{optional<optional<int>>()};
|
||||||
|
VERIFY(!w6);
|
||||||
|
optional<Widget> w7 = optional<optional<int>>();
|
||||||
|
VERIFY(!w7);
|
||||||
|
optional<Widget> w8{optional<optional<short>>()};
|
||||||
|
VERIFY(!w8);
|
||||||
|
static_assert(!std::is_convertible<optional<optional<short>>&&,
|
||||||
|
optional<Widget>>::value);
|
||||||
|
optional<Widget> w10{optional<optional<short>>(10)};
|
||||||
|
VERIFY(w10);
|
||||||
|
optional<Widget> w11 = std::experimental::nullopt;
|
||||||
|
VERIFY(!w11);
|
||||||
|
optional<Widget> w12 = {};
|
||||||
|
VERIFY(!w12);
|
||||||
|
optional<Widget> w13{std::experimental::nullopt};
|
||||||
|
VERIFY(!w13);
|
||||||
|
optional<Widget> w14;
|
||||||
|
w14 = {};
|
||||||
|
VERIFY(!w14);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Widget2
|
||||||
|
{
|
||||||
|
Widget2(int) {}
|
||||||
|
Widget2(optional<int>) {}
|
||||||
|
Widget2& operator=(int) {return *this;}
|
||||||
|
Widget2& operator=(optional<int>) {return *this;}
|
||||||
|
};
|
||||||
|
|
||||||
|
void test04()
|
||||||
|
{
|
||||||
|
optional<Widget2> w;
|
||||||
|
w = optional<int>();
|
||||||
|
VERIFY(w);
|
||||||
|
w = optional<short>();
|
||||||
|
VERIFY(w);
|
||||||
|
w = optional<optional<int>>();
|
||||||
|
VERIFY(!w);
|
||||||
|
w = optional<optional<short>>();
|
||||||
|
VERIFY(!w);
|
||||||
|
w = optional<optional<short>>(10);
|
||||||
|
optional<Widget2> w2 = std::experimental::nullopt;
|
||||||
|
VERIFY(!w2);
|
||||||
|
optional<Widget2> w3 = {};
|
||||||
|
VERIFY(!w3);
|
||||||
|
optional<Widget2> w4{std::experimental::nullopt};
|
||||||
|
VERIFY(!w4);
|
||||||
|
optional<Widget2> w5;
|
||||||
|
w5 = {};
|
||||||
|
VERIFY(!w5);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Thingy
|
||||||
|
{
|
||||||
|
Thingy(int) {}
|
||||||
|
Thingy(Widget) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
void test05()
|
||||||
|
{
|
||||||
|
optional<Thingy> ot;
|
||||||
|
|
||||||
|
static_assert(!std::is_assignable<optional<Thingy>&,
|
||||||
|
optional<int>>::value);
|
||||||
|
static_assert(std::is_assignable<optional<Thingy>&,
|
||||||
|
optional<short>>::value);
|
||||||
|
static_assert(!std::is_assignable<optional<Thingy>&,
|
||||||
|
optional<optional<int>>>::value);
|
||||||
|
ot = optional<Widget>();
|
||||||
|
VERIFY(!ot);
|
||||||
|
optional<Thingy> ot2{optional<int>()};
|
||||||
|
VERIFY(ot2);
|
||||||
|
static_assert(!std::is_convertible<optional<int>&&,
|
||||||
|
optional<Thingy>>::value);
|
||||||
|
optional<Thingy> ot3{optional<short>()};
|
||||||
|
VERIFY(!ot3);
|
||||||
|
optional<Thingy> ot4 = optional<short>();
|
||||||
|
VERIFY(!ot4);
|
||||||
|
|
||||||
|
optional<Thingy> ot5{optional<optional<int>>()};
|
||||||
|
VERIFY(!ot5);
|
||||||
|
static_assert(!std::is_convertible<optional<optional<int>>&&,
|
||||||
|
optional<Thingy>>::value);
|
||||||
|
|
||||||
|
optional<Thingy> ot7{optional<Widget>()};
|
||||||
|
VERIFY(!ot7);
|
||||||
|
optional<Thingy> ot8 = optional<Widget>();
|
||||||
|
VERIFY(!ot8);
|
||||||
|
static_assert(!std::is_constructible<optional<Thingy>,
|
||||||
|
optional<optional<short>>>::value);
|
||||||
|
static_assert(!std::is_convertible<optional<optional<short>>,
|
||||||
|
optional<Thingy>>::value);
|
||||||
|
static_assert(!std::is_assignable<optional<Thingy>&,
|
||||||
|
optional<optional<short>>>::value);
|
||||||
|
optional<Thingy> ot9 = std::experimental::nullopt;
|
||||||
|
VERIFY(!ot9);
|
||||||
|
optional<Thingy> ot10 = {};
|
||||||
|
VERIFY(!ot10);
|
||||||
|
optional<Thingy> ot11{std::experimental::nullopt};
|
||||||
|
VERIFY(!ot11);
|
||||||
|
optional<Thingy> ot12;
|
||||||
|
ot12 = {};
|
||||||
|
VERIFY(!ot12);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RvalueConstructible
|
||||||
|
{
|
||||||
|
RvalueConstructible(int) {}
|
||||||
|
RvalueConstructible(optional<int>&&) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
void test06()
|
||||||
|
{
|
||||||
|
optional<int> oi;
|
||||||
|
optional<RvalueConstructible> ori;
|
||||||
|
static_assert(!std::is_assignable<optional<RvalueConstructible>&,
|
||||||
|
optional<int>&>::value);
|
||||||
|
ori = std::move(oi);
|
||||||
|
VERIFY(ori);
|
||||||
|
|
||||||
|
optional<optional<int>> ooi;
|
||||||
|
static_assert(!std::is_assignable<optional<RvalueConstructible>&,
|
||||||
|
optional<optional<int>>&>::value);
|
||||||
|
ori = std::move(ooi);
|
||||||
|
VERIFY(!ori);
|
||||||
|
|
||||||
|
static_assert(!std::is_constructible<optional<RvalueConstructible>,
|
||||||
|
optional<int>&>::value);
|
||||||
|
static_assert(!std::is_convertible<optional<int>&,
|
||||||
|
optional<RvalueConstructible>>::value);
|
||||||
|
|
||||||
|
optional<RvalueConstructible> ori2(std::move(oi));
|
||||||
|
VERIFY(ori2);
|
||||||
|
optional<RvalueConstructible> ori3 = std::move(oi);
|
||||||
|
VERIFY(ori3);
|
||||||
|
|
||||||
|
static_assert(!std::is_constructible<optional<RvalueConstructible>,
|
||||||
|
optional<optional<int>>&>::value);
|
||||||
|
static_assert(!std::is_convertible<optional<optional<int>>&,
|
||||||
|
optional<RvalueConstructible>>::value);
|
||||||
|
optional<RvalueConstructible> ori6(std::move(ooi));
|
||||||
|
VERIFY(!ori6);
|
||||||
|
optional<RvalueConstructible> ori7 = std::move(ooi);
|
||||||
|
VERIFY(!ori7);
|
||||||
|
optional<RvalueConstructible> ori8 = std::experimental::nullopt;
|
||||||
|
VERIFY(!ori8);
|
||||||
|
optional<RvalueConstructible> ori9 = {};
|
||||||
|
VERIFY(!ori9);
|
||||||
|
optional<RvalueConstructible> ori10{std::experimental::nullopt};
|
||||||
|
VERIFY(!ori10);
|
||||||
|
optional<RvalueConstructible> ori11;
|
||||||
|
ori11 = {};
|
||||||
|
VERIFY(!ori11);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Thingy2
|
||||||
|
{
|
||||||
|
Thingy2(int) {}
|
||||||
|
explicit Thingy2(optional<int>) {}
|
||||||
|
Thingy2(Widget) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
void test07()
|
||||||
|
{
|
||||||
|
optional<Thingy2> ot{optional<int>{}};
|
||||||
|
VERIFY(ot);
|
||||||
|
static_assert(!std::is_convertible<optional<int>,
|
||||||
|
optional<Thingy2>>::value);
|
||||||
|
optional<Thingy2> ot2{optional<short>{}};
|
||||||
|
VERIFY(ot2);
|
||||||
|
static_assert(!std::is_convertible<optional<short>,
|
||||||
|
optional<Thingy2>>::value);
|
||||||
|
optional<Thingy2> ot3{optional<optional<int>>{}};
|
||||||
|
VERIFY(!ot3);
|
||||||
|
static_assert(!std::is_convertible<optional<optional<int>>,
|
||||||
|
optional<Thingy2>>::value);
|
||||||
|
optional<Thingy2> ot4{optional<optional<short>>{}};
|
||||||
|
VERIFY(!ot4);
|
||||||
|
static_assert(!std::is_convertible<optional<optional<short>>,
|
||||||
|
optional<Thingy2>>::value);
|
||||||
|
|
||||||
|
optional<Thingy2> ot5{optional<Widget>{}};
|
||||||
|
VERIFY(!ot5);
|
||||||
|
optional<Thingy2> ot6 = optional<Widget>();
|
||||||
|
VERIFY(!ot6);
|
||||||
|
|
||||||
|
static_assert(!std::is_assignable<optional<Thingy2>&,
|
||||||
|
optional<int>>::value);
|
||||||
|
static_assert(!std::is_assignable<optional<Thingy2>&,
|
||||||
|
optional<short>>::value);
|
||||||
|
static_assert(!std::is_assignable<optional<Thingy2>&,
|
||||||
|
optional<optional<int>>>::value);
|
||||||
|
static_assert(!std::is_assignable<optional<Thingy2>&,
|
||||||
|
optional<optional<short>>>::value);
|
||||||
|
optional<Thingy2> ot7;
|
||||||
|
ot = optional<Widget>();
|
||||||
|
VERIFY(!ot7);
|
||||||
|
optional<Thingy2> ot8 = std::experimental::nullopt;
|
||||||
|
VERIFY(!ot8);
|
||||||
|
optional<Thingy2> ot9 = {};
|
||||||
|
VERIFY(!ot9);
|
||||||
|
optional<Thingy2> ot10{std::experimental::nullopt};
|
||||||
|
VERIFY(!ot10);
|
||||||
|
optional<Thingy2> ot11;
|
||||||
|
ot11 = {};
|
||||||
|
VERIFY(!ot11);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Thingy3
|
||||||
|
{
|
||||||
|
Thingy3(int) {}
|
||||||
|
template<class... Args,
|
||||||
|
std::enable_if_t<std::is_constructible<Widget, Args&&...>::value,
|
||||||
|
bool> = true>
|
||||||
|
explicit Thingy3(Args&&... args) {}
|
||||||
|
Thingy3(Widget) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
void test08()
|
||||||
|
{
|
||||||
|
optional<Thingy3> ot{optional<int>{}};
|
||||||
|
VERIFY(ot);
|
||||||
|
static_assert(!std::is_convertible<optional<int>,
|
||||||
|
optional<Thingy3>>::value);
|
||||||
|
optional<Thingy3> ot2{optional<short>{}};
|
||||||
|
VERIFY(ot2);
|
||||||
|
static_assert(!std::is_convertible<optional<short>,
|
||||||
|
optional<Thingy3>>::value);
|
||||||
|
optional<Thingy3> ot3{optional<optional<int>>{}};
|
||||||
|
VERIFY(!ot3);
|
||||||
|
static_assert(!std::is_convertible<optional<optional<int>>,
|
||||||
|
optional<Thingy3>>::value);
|
||||||
|
optional<Thingy3> ot4{optional<optional<short>>{}};
|
||||||
|
VERIFY(!ot4);
|
||||||
|
static_assert(!std::is_convertible<optional<optional<short>>,
|
||||||
|
optional<Thingy3>>::value);
|
||||||
|
|
||||||
|
optional<Thingy3> ot5{optional<Widget>{}};
|
||||||
|
VERIFY(!ot5);
|
||||||
|
optional<Thingy3> ot6 = optional<Widget>();
|
||||||
|
VERIFY(!ot6);
|
||||||
|
|
||||||
|
static_assert(!std::is_assignable<optional<Thingy3>&,
|
||||||
|
optional<int>>::value);
|
||||||
|
static_assert(!std::is_assignable<optional<Thingy3>&,
|
||||||
|
optional<short>>::value);
|
||||||
|
static_assert(!std::is_assignable<optional<Thingy3>&,
|
||||||
|
optional<optional<int>>>::value);
|
||||||
|
static_assert(!std::is_assignable<optional<Thingy3>&,
|
||||||
|
optional<optional<short>>>::value);
|
||||||
|
optional<Thingy3> ot7;
|
||||||
|
ot = optional<Widget>();
|
||||||
|
VERIFY(!ot7);
|
||||||
|
optional<Thingy3> ot8 = std::experimental::nullopt;
|
||||||
|
VERIFY(!ot8);
|
||||||
|
optional<Thingy3> ot9 = {};
|
||||||
|
VERIFY(!ot9);
|
||||||
|
optional<Thingy3> ot10{std::experimental::nullopt};
|
||||||
|
VERIFY(!ot10);
|
||||||
|
optional<Thingy3> ot11;
|
||||||
|
ot11 = {};
|
||||||
|
VERIFY(!ot11);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test09()
|
||||||
|
{
|
||||||
|
std::experimental::any a = 42;
|
||||||
|
optional<std::experimental::any> oa2 = a;
|
||||||
|
VERIFY(oa2);
|
||||||
|
VERIFY(std::experimental::any_cast<int>(*oa2) == 42);
|
||||||
|
optional<std::experimental::any> oa3 = oa2;
|
||||||
|
VERIFY(oa3);
|
||||||
|
VERIFY(std::experimental::any_cast<int>(*oa3) == 42);
|
||||||
|
optional<std::experimental::any> oa4{oa2};
|
||||||
|
VERIFY(oa4);
|
||||||
|
VERIFY(std::experimental::any_cast<int>(*oa4) == 42);
|
||||||
|
optional<std::experimental::any> oa5(oa2);
|
||||||
|
VERIFY(oa5);
|
||||||
|
VERIFY(std::experimental::any_cast<int>(*oa5) == 42);
|
||||||
|
optional<std::experimental::any> oa6;
|
||||||
|
VERIFY(!oa6);
|
||||||
|
optional<std::experimental::any> oa7 = oa6;
|
||||||
|
VERIFY(!oa7);
|
||||||
|
optional<std::experimental::any> oa8{oa6};
|
||||||
|
VERIFY(!oa8);
|
||||||
|
optional<std::experimental::any> oa9(oa6);
|
||||||
|
VERIFY(!oa9);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test10()
|
||||||
|
{
|
||||||
|
struct X {};
|
||||||
|
optional<int> oi(std::experimental::in_place);
|
||||||
|
oi = {};
|
||||||
|
VERIFY(bool(oi) == false);
|
||||||
|
optional<X> ot(std::experimental::in_place);
|
||||||
|
ot = {};
|
||||||
|
VERIFY(bool(ot) == false);
|
||||||
|
optional<int> oi2(std::experimental::in_place);
|
||||||
|
short int si = 6;
|
||||||
|
oi2 = si;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test01();
|
||||||
|
test02();
|
||||||
|
test03();
|
||||||
|
test04();
|
||||||
|
test05();
|
||||||
|
test06();
|
||||||
|
test07();
|
||||||
|
test08();
|
||||||
|
test09();
|
||||||
|
test10();
|
||||||
|
}
|
|
@ -18,6 +18,7 @@
|
||||||
// <http://www.gnu.org/licenses/>.
|
// <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#include <experimental/optional>
|
#include <experimental/optional>
|
||||||
|
#include <vector>
|
||||||
#include <testsuite_hooks.h>
|
#include <testsuite_hooks.h>
|
||||||
|
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
|
@ -61,5 +62,15 @@ int main()
|
||||||
VERIFY( !o );
|
VERIFY( !o );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::experimental::optional<std::vector<int>> ovi{{1, 2, 3}};
|
||||||
|
VERIFY(ovi->size() == 3);
|
||||||
|
VERIFY((*ovi)[0] == 1 && (*ovi)[1] == 2 && (*ovi)[2] == 3);
|
||||||
|
ovi = {4, 5, 6, 7};
|
||||||
|
VERIFY(ovi->size() == 4);
|
||||||
|
VERIFY((*ovi)[0] == 4 && (*ovi)[1] == 5 &&
|
||||||
|
(*ovi)[2] == 6 && (*ovi)[3] == 7);
|
||||||
|
}
|
||||||
|
|
||||||
VERIFY( counter == 0 );
|
VERIFY( counter == 0 );
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
// { dg-do run { target c++14 } }
|
||||||
|
|
||||||
|
// Copyright (C) 2016 Free Software Foundation, Inc.
|
||||||
|
//
|
||||||
|
// This file is part of the GNU ISO C++ Library. This library is free
|
||||||
|
// software; you can redistribute it and/or modify it under the
|
||||||
|
// terms of the GNU General Public License as published by the
|
||||||
|
// Free Software Foundation; either version 3, or (at your option)
|
||||||
|
// any later version.
|
||||||
|
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a moved_to of the GNU General Public License along
|
||||||
|
// with this library; see the file COPYING3. If not see
|
||||||
|
// <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include <experimental/optional>
|
||||||
|
#include <testsuite_hooks.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct NonTransferable
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
NonTransferable(int x) : x(x) {}
|
||||||
|
NonTransferable(NonTransferable&&) = delete;
|
||||||
|
NonTransferable& operator=(NonTransferable&&) = delete;
|
||||||
|
operator int() {return x;}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::experimental::optional<int> oi;
|
||||||
|
std::experimental::optional<NonTransferable> ot(std::move(oi));
|
||||||
|
VERIFY(!ot);
|
||||||
|
|
||||||
|
std::experimental::optional<int> oi2;
|
||||||
|
std::experimental::optional<NonTransferable> ot2(oi2);
|
||||||
|
VERIFY(!ot);
|
||||||
|
|
||||||
|
std::experimental::optional<int> oi3{42};
|
||||||
|
std::experimental::optional<NonTransferable> ot3(std::move(oi3));
|
||||||
|
VERIFY(ot3 && *ot3 == 42);
|
||||||
|
|
||||||
|
std::experimental::optional<int> oi4{666};
|
||||||
|
std::experimental::optional<NonTransferable> ot4(oi4);
|
||||||
|
VERIFY(ot4 && *ot4 == 666);
|
||||||
|
}
|
|
@ -254,4 +254,31 @@ int main()
|
||||||
std::experimental::optional<X> ox4;
|
std::experimental::optional<X> ox4;
|
||||||
ox4 = oi;
|
ox4 = oi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::experimental::optional<std::experimental::optional<int>> ooi =
|
||||||
|
std::experimental::optional<int>();
|
||||||
|
VERIFY(bool(ooi));
|
||||||
|
ooi = std::experimental::optional<int>();
|
||||||
|
VERIFY(bool(ooi));
|
||||||
|
ooi = std::experimental::optional<int>(42);
|
||||||
|
VERIFY(bool(ooi));
|
||||||
|
VERIFY(bool(*ooi));
|
||||||
|
std::experimental::optional<std::experimental::optional<int>> ooi2 =
|
||||||
|
std::experimental::optional<short>();
|
||||||
|
VERIFY(bool(ooi2));
|
||||||
|
ooi2 = std::experimental::optional<short>();
|
||||||
|
VERIFY(bool(ooi2));
|
||||||
|
ooi2 = std::experimental::optional<short>(6);
|
||||||
|
VERIFY(bool(ooi2));
|
||||||
|
VERIFY(bool(*ooi2));
|
||||||
|
std::experimental::optional<std::experimental::optional<int>> ooi3 =
|
||||||
|
std::experimental::optional<int>(42);
|
||||||
|
VERIFY(bool(ooi3));
|
||||||
|
VERIFY(bool(*ooi3));
|
||||||
|
std::experimental::optional<std::experimental::optional<int>> ooi4 =
|
||||||
|
std::experimental::optional<short>(6);
|
||||||
|
VERIFY(bool(ooi4));
|
||||||
|
VERIFY(bool(*ooi4));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue