aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVille Voutilainen <ville.voutilainen@gmail.com>2016-07-06 16:26:10 +0300
committerVille Voutilainen <ville@gcc.gnu.org>2016-07-06 16:26:10 +0300
commit6ffe854859e61fd04e1db8694e2c519f4010647b (patch)
tree957dd6c8746ccbf44024331b3ac6724659ec9dbe
parente4bbb037670323fbc578b6bc68cfb5252f1bf0cc (diff)
downloadgcc-6ffe854859e61fd04e1db8694e2c519f4010647b.zip
gcc-6ffe854859e61fd04e1db8694e2c519f4010647b.tar.gz
gcc-6ffe854859e61fd04e1db8694e2c519f4010647b.tar.bz2
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
-rw-r--r--libstdc++-v3/ChangeLog15
-rw-r--r--libstdc++-v3/include/experimental/optional148
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/cons/value.cc19
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/cons/value_neg.cc39
4 files changed, 219 insertions, 2 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index d888864..46f7f74 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -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>
Implement LWG 2509,
diff --git a/libstdc++-v3/include/experimental/optional b/libstdc++-v3/include/experimental/optional
index 7524a7e..b6425b7 100644
--- a/libstdc++-v3/include/experimental/optional
+++ b/libstdc++-v3/include/experimental/optional
@@ -470,6 +470,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
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.
*/
@@ -502,6 +519,78 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// _Optional_base has the responsibility for construction.
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.
optional&
operator=(nullopt_t) noexcept
@@ -510,8 +599,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return *this;
}
- template<typename _Up>
- enable_if_t<is_same<_Tp, decay_t<_Up>>::value, optional&>
+ template<typename _Up,
+ enable_if_t<__and_<
+ __not_<is_same<_Up, nullopt_t>>,
+ __not_<__is_optional<_Up>>>::value,
+ bool> = true>
+ optional&
operator=(_Up&& __u)
{
static_assert(__and_<is_constructible<_Tp, _Up>,
@@ -526,6 +619,57 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
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>
void
emplace(_Args&&... __args)
diff --git a/libstdc++-v3/testsuite/experimental/optional/cons/value.cc b/libstdc++-v3/testsuite/experimental/optional/cons/value.cc
index a916951..123a89e 100644
--- a/libstdc++-v3/testsuite/experimental/optional/cons/value.cc
+++ b/libstdc++-v3/testsuite/experimental/optional/cons/value.cc
@@ -22,6 +22,7 @@
#include <testsuite_hooks.h>
#include <vector>
+#include <string>
struct tracker
{
@@ -236,4 +237,22 @@ int main()
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;
+ }
}
diff --git a/libstdc++-v3/testsuite/experimental/optional/cons/value_neg.cc b/libstdc++-v3/testsuite/experimental/optional/cons/value_neg.cc
new file mode 100644
index 0000000..c862a04
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/cons/value_neg.cc
@@ -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" }
+ }
+}