Commit 6ffe8548 by Ville Voutilainen Committed by Ville Voutilainen

Implement LWG 2451, optional<T> should 'forward' T's implicit conversions.

	Implement LWG 2451, optional<T> should 'forward' T's
	implicit conversions.
	* include/experimental/optional (__is_optional_impl, __is_optional):
	New.
	(optional()): Make constexpr and default.
	(optional(_Up&&), optional(const optional<_Up>&),
	optional(optional<_Up>&& __t): New.
	(operator=(_Up&&)): Constrain.
	(operator=(const optional<_Up>&), operator=(optional<_Up>&&)): New.
	* testsuite/experimental/optional/cons/value.cc:
	Add tests for the functionality added by LWG 2451.
	* testsuite/experimental/optional/cons/value_neg.cc: New.

From-SVN: r238049
parent e4bbb037
2016-07-06 Ville Voutilainen <ville.voutilainen@gmail.com>
Implement LWG 2451, optional<T> should 'forward' T's
implicit conversions.
* include/experimental/optional (__is_optional_impl, __is_optional):
New.
(optional()): Make constexpr and default.
(optional(_Up&&), optional(const optional<_Up>&),
optional(optional<_Up>&& __t): New.
(operator=(_Up&&)): Constrain.
(operator=(const optional<_Up>&), operator=(optional<_Up>&&)): New.
* testsuite/experimental/optional/cons/value.cc:
Add tests for the functionality added by LWG 2451.
* testsuite/experimental/optional/cons/value_neg.cc: New.
2016-07-05 Ville Voutilainen <ville.voutilainen@gmail.com> 2016-07-05 Ville Voutilainen <ville.voutilainen@gmail.com>
Implement LWG 2509, Implement LWG 2509,
......
...@@ -470,6 +470,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -470,6 +470,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
bool _M_engaged = false; bool _M_engaged = false;
}; };
template<typename _Tp>
class optional;
template<typename>
struct __is_optional_impl : false_type
{ };
template<typename _Tp>
struct __is_optional_impl<optional<_Tp>> : true_type
{ };
template<typename _Tp>
struct __is_optional
: public __is_optional_impl<std::remove_cv_t<std::remove_reference_t<_Tp>>>
{ };
/** /**
* @brief Class template for optional values. * @brief Class template for optional values.
*/ */
...@@ -502,6 +519,78 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -502,6 +519,78 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// _Optional_base has the responsibility for construction. // _Optional_base has the responsibility for construction.
using _Base::_Base; using _Base::_Base;
constexpr optional() = default;
// Converting constructors for engaged optionals.
template <typename _Up,
enable_if_t<__and_<
__not_<is_same<_Tp, _Up>>,
is_constructible<_Tp, _Up&&>,
is_convertible<_Up&&, _Tp>
>::value, bool> = true>
constexpr optional(_Up&& __t)
: _Base(_Tp(std::forward<_Up>(__t))) { }
template <typename _Up,
enable_if_t<__and_<
__not_<is_same<_Tp, _Up>>,
is_constructible<_Tp, _Up&&>,
__not_<is_convertible<_Up&&, _Tp>>
>::value, bool> = false>
explicit constexpr optional(_Up&& __t)
: _Base(_Tp(std::forward<_Up>(__t))) { }
template <typename _Up,
enable_if_t<__and_<
__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_convertible<const _Up&, _Tp>
>::value, bool> = true>
constexpr optional(const optional<_Up>& __t)
: _Base(__t ? optional<_Tp>(*__t) : optional<_Tp>()) { }
template <typename _Up,
enable_if_t<__and_<
__not_<is_same<_Tp, _Up>>,
__not_<is_constructible<
_Tp, const optional<_Up>&>>,
__not_<is_convertible<
const optional<_Up>&, _Tp>>,
is_constructible<_Tp, const _Up&>,
__not_<is_convertible<const _Up&, _Tp>>
>::value, bool> = false>
explicit constexpr optional(const optional<_Up>& __t)
: _Base(__t ? optional<_Tp>(*__t) : optional<_Tp>()) { }
template <typename _Up,
enable_if_t<__and_<
__not_<is_same<_Tp, _Up>>,
__not_<is_constructible<
_Tp, optional<_Up>&&>>,
__not_<is_convertible<
optional<_Up>&&, _Tp>>,
is_constructible<_Tp, _Up&&>,
is_convertible<_Up&&, _Tp>
>::value, bool> = true>
constexpr optional(optional<_Up>&& __t)
: _Base(__t ? optional<_Tp>(std::move(*__t)) : optional<_Tp>()) { }
template <typename _Up,
enable_if_t<__and_<
__not_<is_same<_Tp, _Up>>,
__not_<is_constructible<
_Tp, optional<_Up>&&>>,
__not_<is_convertible<
optional<_Up>&&, _Tp>>,
is_constructible<_Tp, _Up&&>,
__not_<is_convertible<_Up&&, _Tp>>
>::value, bool> = false>
explicit constexpr optional(optional<_Up>&& __t)
: _Base(__t ? optional<_Tp>(std::move(*__t)) : optional<_Tp>()) { }
// [X.Y.4.3] (partly) Assignment. // [X.Y.4.3] (partly) Assignment.
optional& optional&
operator=(nullopt_t) noexcept operator=(nullopt_t) noexcept
...@@ -510,8 +599,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -510,8 +599,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return *this; return *this;
} }
template<typename _Up> template<typename _Up,
enable_if_t<is_same<_Tp, decay_t<_Up>>::value, optional&> enable_if_t<__and_<
__not_<is_same<_Up, nullopt_t>>,
__not_<__is_optional<_Up>>>::value,
bool> = true>
optional&
operator=(_Up&& __u) operator=(_Up&& __u)
{ {
static_assert(__and_<is_constructible<_Tp, _Up>, static_assert(__and_<is_constructible<_Tp, _Up>,
...@@ -526,6 +619,57 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -526,6 +619,57 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return *this; return *this;
} }
template<typename _Up,
enable_if_t<__and_<
__not_<is_same<_Tp, _Up>>>::value,
bool> = true>
optional&
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 (this->_M_is_engaged())
this->_M_get() = *__u;
else
this->_M_construct(*__u);
}
else
{
this->_M_reset();
}
return *this;
}
template<typename _Up,
enable_if_t<__and_<
__not_<is_same<_Tp, _Up>>>::value,
bool> = true>
optional&
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 (this->_M_is_engaged())
this->_M_get() = std::move(*__u);
else
this->_M_construct(std::move(*__u));
}
else
{
this->_M_reset();
}
return *this;
}
template<typename... _Args> template<typename... _Args>
void void
emplace(_Args&&... __args) emplace(_Args&&... __args)
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <testsuite_hooks.h> #include <testsuite_hooks.h>
#include <vector> #include <vector>
#include <string>
struct tracker struct tracker
{ {
...@@ -236,4 +237,22 @@ int main() ...@@ -236,4 +237,22 @@ int main()
VERIFY( result == caught ); VERIFY( result == caught );
} }
{
std::experimental::optional<std::string> os = "foo";
struct X
{
explicit X(int) {}
X& operator=(int) {return *this;}
};
std::experimental::optional<X> ox{42};
std::experimental::optional<int> oi{42};
std::experimental::optional<X> ox2{oi};
std::experimental::optional<std::string> os2;
os2 = "foo";
std::experimental::optional<X> ox3;
ox3 = 42;
std::experimental::optional<X> ox4;
ox4 = oi;
}
} }
// { dg-options "-std=gnu++14" }
// { dg-do compile }
// Copyright (C) 2013-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>
#include <string>
#include <memory>
int main()
{
{
struct X
{
explicit X(int) {}
};
std::experimental::optional<X> ox{42};
std::experimental::optional<X> ox2 = 42; // { dg-error "conversion" }
std::experimental::optional<std::unique_ptr<int>> oup{new int};
std::experimental::optional<std::unique_ptr<int>> oup2 = new int; // { dg-error "conversion" }
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment