diff mbox

[v3] Implement LWG 2744 and LWG 2754.

Message ID CAFk2RUbhQ1x6Ev4Li67rZok9awi20954g6Y4axzGC7ZY0RkpAA@mail.gmail.com
State New
Headers show

Commit Message

Ville Voutilainen Aug. 9, 2016, 3 p.m. UTC
Tested on Linux-x64.

2016-08-09  Ville Voutilainen  <ville.voutilainen@gmail.com>

    Implement LWG 2744 and LWG 2754.
    * include/std/any (any(ValueType&&)): Constrain with __is_in_place.
    (any(in_place_type_t<_ValueType>, _Args&&...)): Use _Decay.
    (any(in_place_type_t<_ValueType>, initializer_list<_Up>, _Args&&...)):
    Likewise.
    (emplace(_Args&&...)): Likewise.
    (emplace(initializer_list<_Up>, _Args&&...)): Likewise.
    * include/std/utility: (__is_in_place_impl, __is_in_place): New.
    * testsuite/20_util/any/assign/emplace.cc: Add tests for decaying
    emplace.
    * testsuite/20_util/any/cons/in_place.cc: Add tests for decaying
    in_place constructor.
    * testsuite/20_util/any/misc/any_cast_neg.cc: Adjust.

Comments

Jonathan Wakely Aug. 15, 2016, 9:53 a.m. UTC | #1
On 09/08/16 18:00 +0300, Ville Voutilainen wrote:
 				    _Args&&...> = false>
>diff --git a/libstdc++-v3/include/std/utility b/libstdc++-v3/include/std/utility
>index 0c03644..e1a523f 100644
>--- a/libstdc++-v3/include/std/utility
>+++ b/libstdc++-v3/include/std/utility
>@@ -356,6 +356,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>   template <size_t _Idx>
>     in_place_tag in_place(__in_place_index<_Idx>*) {terminate();}
>
>+  template<typename>
>+    struct __is_in_place_impl : false_type
>+    { };
>+
>+  template<typename _Tp>
>+  struct __is_in_place_impl<in_place_type_t<_Tp>> : true_type

Indentation nit.

>+    { };
>+
>+  template<typename _Tp>
>+    struct __is_in_place
>+    : public __is_in_place_impl<std::remove_cv_t<std::remove_reference_t<_Tp>>>

Any reason not to use decay_t here? In all the cases where decay is
different to stripping references and cv-qualifiers the result will be
false either way.

I wouldn't have bothered with the std:: qualification either, but it's
fine as it is.

OK for trunk, thanks.
Ville Voutilainen Aug. 15, 2016, 11:55 a.m. UTC | #2
On 15 August 2016 at 12:53, Jonathan Wakely <jwakely@redhat.com> wrote:
>> +  template<typename>
>> +    struct __is_in_place_impl : false_type
>> +    { };
>> +
>> +  template<typename _Tp>
>> +  struct __is_in_place_impl<in_place_type_t<_Tp>> : true_type
> Indentation nit.

Will fix.

>
>> +    { };
>> +
>> +  template<typename _Tp>
>> +    struct __is_in_place
>> +    : public
>> __is_in_place_impl<std::remove_cv_t<std::remove_reference_t<_Tp>>>
>
>
> Any reason not to use decay_t here? In all the cases where decay is
> different to stripping references and cv-qualifiers the result will be
> false either way.
>
> I wouldn't have bothered with the std:: qualification either, but it's
> fine as it is.


The reason for not using decay and for the qualification is that the
trait is closely
related to its copy-paste origin, which is __is_optional. ;) I should
also add a test
for the case where in_place is attempted to pass through the
ValueType&& parameter,
aka a case where a type is not default-constructible but is
constructible from in_place,
and in_place-construction is used.
diff mbox

Patch

diff --git a/libstdc++-v3/include/std/any b/libstdc++-v3/include/std/any
index 4add118..27325c5 100644
--- a/libstdc++-v3/include/std/any
+++ b/libstdc++-v3/include/std/any
@@ -153,7 +153,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     /// Construct with a copy of @p __value as the contained object.
     template <typename _ValueType, typename _Tp = _Decay<_ValueType>,
 	      typename _Mgr = _Manager<_Tp>,
-              __any_constructible_t<_Tp, _ValueType&&> = true>
+              __any_constructible_t<_Tp, _ValueType&&> = true,
+	      enable_if_t<!__is_in_place<_Tp>::value, bool> = true>
       any(_ValueType&& __value)
       : _M_manager(&_Mgr::_S_manage)
       {
@@ -164,9 +165,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     template <typename _ValueType, typename _Tp = _Decay<_ValueType>,
 	      typename _Mgr = _Manager<_Tp>,
               enable_if_t<__and_<is_copy_constructible<_Tp>,
-				 __not_<
-				   is_constructible<_Tp,
-						    _ValueType&&>>>::value,
+				 __not_<is_constructible<_Tp, _ValueType&&>>,
+			         __not_<__is_in_place<_Tp>>>::value,
 			  bool> = false>
       any(_ValueType&& __value)
       : _M_manager(&_Mgr::_S_manage)
@@ -175,10 +175,11 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       }
 
     /// Construct with an object created from @p __args as the contained object.
-    template <typename _Tp, typename... _Args,
+    template <typename _ValueType, typename... _Args,
+	      typename _Tp = _Decay<_ValueType>,
 	      typename _Mgr = _Manager<_Tp>,
               __any_constructible_t<_Tp, _Args&&...> = false>
-      any(in_place_type_t<_Tp>, _Args&&... __args)
+      any(in_place_type_t<_ValueType>, _Args&&... __args)
       : _M_manager(&_Mgr::_S_manage)
       {
         _Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...);
@@ -186,11 +187,13 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
     /// Construct with an object created from @p __il and @p __args as
     /// the contained object.
-    template <typename _Tp, typename _Up, typename... _Args,
+    template <typename _ValueType, typename _Up, typename... _Args,
+	      typename _Tp = _Decay<_ValueType>,
 	      typename _Mgr = _Manager<_Tp>,
               __any_constructible_t<_Tp, initializer_list<_Up>,
 				    _Args&&...> = false>
-      any(in_place_type_t<_Tp>, initializer_list<_Up> __il, _Args&&... __args)
+      any(in_place_type_t<_ValueType>,
+	  initializer_list<_Up> __il, _Args&&... __args)
       : _M_manager(&_Mgr::_S_manage)
       {
         _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...);
@@ -248,7 +251,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       }
 
     /// Emplace with an object created from @p __args as the contained object.
-    template <typename _Tp, typename... _Args,
+    template <typename _ValueType, typename... _Args,
+	      typename _Tp = _Decay<_ValueType>,
 	      typename _Mgr = _Manager<_Tp>,
               __any_constructible_t<_Tp, _Args&&...> = false>
       void emplace(_Args&&... __args)
@@ -260,7 +264,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
     /// Emplace with an object created from @p __il and @p __args as
     /// the contained object.
-    template <typename _Tp, typename _Up, typename... _Args,
+    template <typename _ValueType, typename _Up, typename... _Args,
+	      typename _Tp = _Decay<_ValueType>,
 	      typename _Mgr = _Manager<_Tp>,
               __any_constructible_t<_Tp, initializer_list<_Up>,
 				    _Args&&...> = false>
diff --git a/libstdc++-v3/include/std/utility b/libstdc++-v3/include/std/utility
index 0c03644..e1a523f 100644
--- a/libstdc++-v3/include/std/utility
+++ b/libstdc++-v3/include/std/utility
@@ -356,6 +356,19 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template <size_t _Idx>
     in_place_tag in_place(__in_place_index<_Idx>*) {terminate();}
 
+  template<typename>
+    struct __is_in_place_impl : false_type
+    { };
+
+  template<typename _Tp>
+  struct __is_in_place_impl<in_place_type_t<_Tp>> : true_type
+    { };
+
+  template<typename _Tp>
+    struct __is_in_place
+    : public __is_in_place_impl<std::remove_cv_t<std::remove_reference_t<_Tp>>>
+    { };
+
 #define  __cpp_lib_as_const 201510
   template<typename _Tp>
     constexpr add_const_t<_Tp>& as_const(_Tp& __t) noexcept { return __t; }
@@ -363,7 +376,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     void as_const(const _Tp&&) = delete;
 
-#endif
+#endif // C++17
 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
diff --git a/libstdc++-v3/testsuite/20_util/any/assign/emplace.cc b/libstdc++-v3/testsuite/20_util/any/assign/emplace.cc
index 663bae2..df37f78 100644
--- a/libstdc++-v3/testsuite/20_util/any/assign/emplace.cc
+++ b/libstdc++-v3/testsuite/20_util/any/assign/emplace.cc
@@ -59,4 +59,18 @@  int main()
   combined& c2 = std::any_cast<combined&>(o5);
   VERIFY(c2.v[0] == 1 && c2.v[1] == 2
 	 && std::get<0>(c2.t) == 3 && std::get<1>(c2.t) == 4 );
+  std::any o6;
+  o6.emplace<const int&>(i);
+  VERIFY(o6.type() == o.type());
+  std::any o7;
+  o7.emplace<void()>(nullptr);
+  std::any o8;
+  o8.emplace<void(*)()>(nullptr);
+  VERIFY(o7.type() == o8.type());
+  std::any o9;
+  o9.emplace<char(&)[42]>(nullptr);
+  std::any o10;
+  o10.emplace<char*>(nullptr);
+  VERIFY(o9.type() == o10.type());
+  
 }
diff --git a/libstdc++-v3/testsuite/20_util/any/cons/in_place.cc b/libstdc++-v3/testsuite/20_util/any/cons/in_place.cc
index 2368b83..52f2b38 100644
--- a/libstdc++-v3/testsuite/20_util/any/cons/in_place.cc
+++ b/libstdc++-v3/testsuite/20_util/any/cons/in_place.cc
@@ -54,4 +54,12 @@  int main()
   combined& c2 = std::any_cast<combined&>(o5);
   VERIFY(c2.v[0] == 1 && c2.v[1] == 2
 	 && std::get<0>(c2.t) == 3 && std::get<1>(c2.t) == 4 );
+  std::any o6(std::in_place<int&>, i);
+  VERIFY(o6.type() == o.type());
+  std::any o7(std::in_place<void()>, nullptr);
+  std::any o8(std::in_place<void(*)()>, nullptr);
+  VERIFY(o7.type() == o8.type());
+  std::any o9(std::in_place<char(&)[42]>, nullptr);
+  std::any o10(std::in_place<char*>, nullptr);
+  VERIFY(o9.type() == o10.type());
 }
diff --git a/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc b/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc
index 32b4e76..05fdeb7 100644
--- a/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc
@@ -26,5 +26,5 @@  void test01()
   using std::any_cast;
 
   const any y(1);
-  any_cast<int&>(y); // { dg-error "qualifiers" "" { target { *-*-* } } 435 }
+  any_cast<int&>(y); // { dg-error "qualifiers" "" { target { *-*-* } } 440 }
 }