mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
e4bbb03767
commit
6ffe854859
|
|
@ -1,3 +1,18 @@
|
||||||
|
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
|
||||||
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
|
||||||
// _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
|
||||||
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
|
||||||
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 @@
|
||||||
#include <testsuite_hooks.h>
|
#include <testsuite_hooks.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
struct tracker
|
struct tracker
|
||||||
{
|
{
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
// { 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" }
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue