Update issue status for LWG 2744
llvm-svn: 284322
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: 50253ed1c67b75c71c8ec2d24ed915c032b11822
diff --git a/include/any b/include/any
index 8fe9e8f..7f2cf1e 100644
--- a/include/any
+++ b/include/any
@@ -200,7 +200,7 @@
, class _Tp = decay_t<_ValueType>
, class = enable_if_t<
!is_same<_Tp, any>::value &&
- !__is_inplace_type<_ValueType>::value &&
+ !__is_inplace_type_tag<_ValueType>::value &&
is_copy_constructible<_Tp>::value>
>
_LIBCPP_INLINE_VISIBILITY
@@ -241,15 +241,12 @@
return *this;
}
- // TODO: Should this be constrained to disallow in_place types like the
- // ValueType constructor?
template <
class _ValueType
, class _Tp = decay_t<_ValueType>
, class = enable_if_t<
!is_same<_Tp, any>::value
- && is_copy_constructible<_Tp>::value
- && !__is_inplace_type<_ValueType>::value>
+ && is_copy_constructible<_Tp>::value>
>
_LIBCPP_INLINE_VISIBILITY
any & operator=(_ValueType && __rhs);
diff --git a/include/utility b/include/utility
index cfab350..5e55506 100644
--- a/include/utility
+++ b/include/utility
@@ -928,10 +928,20 @@
return in_place_tag(__in_place_tag{});
}
-template <class _Tp> struct __is_inplace_type : false_type {};
-template <> struct __is_inplace_type<in_place_t> : true_type {};
-template <class _Tp> struct __is_inplace_type<in_place_type_t<_Tp>> : true_type {};
-template <size_t _Idx> struct __is_inplace_type<in_place_index_t<_Idx>> : true_type {};
+template <class _Tp> struct __is_inplace_tag_imp : false_type {};
+template <> struct __is_inplace_tag_imp<in_place_tag(__in_place_tag)> : true_type {};
+template <class _Tp> struct __is_inplace_tag_imp<in_place_tag(__in_place_type_tag<_Tp>)> : true_type {};
+template <size_t _Idx> struct __is_inplace_tag_imp<in_place_tag(__in_place_index_tag<_Idx>)> : true_type {};
+
+template <class _Tp>
+using __is_inplace_tag = __is_inplace_tag_imp<remove_pointer_t<decay_t<_Tp>>>;
+
+template <class _Tp> struct __is_inplace_type_tag_imp : false_type {};
+template <class _Tp> struct __is_inplace_type_tag_imp<in_place_tag(__in_place_type_tag<_Tp>)> : true_type {};
+
+template <class _Tp>
+using __is_inplace_type_tag = __is_inplace_type_tag_imp<remove_pointer_t<decay_t<_Tp>>>;
+
#endif // _LIBCPP_STD_VER > 14
diff --git a/test/libcxx/utilities/utility/utility.inplace/__is_inplace_tag.pass.cpp b/test/libcxx/utilities/utility/utility.inplace/__is_inplace_tag.pass.cpp
new file mode 100644
index 0000000..057bcf5
--- /dev/null
+++ b/test/libcxx/utilities/utility/utility.inplace/__is_inplace_tag.pass.cpp
@@ -0,0 +1,36 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <utility>
+
+// template <class Tp>
+// struct __is_inplace_tag;
+
+#include <utility>
+#include <cassert>
+
+template <bool Expect, class RefFn, class Fn = std::remove_reference_t<RefFn>>
+void do_test() {
+ static_assert(std::__is_inplace_tag<RefFn>::value == Expect, "");
+ static_assert(std::__is_inplace_tag<Fn>::value == Expect, "");
+ static_assert(std::__is_inplace_tag<std::decay_t<RefFn>>::value == Expect, "");
+ static_assert(std::__is_inplace_tag<Fn*>::value == Expect, "");
+}
+
+int main() {
+ do_test<true, std::in_place_t>();
+ do_test<true, std::in_place_type_t<int>>();
+ do_test<true, std::in_place_index_t<42>>();
+ do_test<false, std::in_place_tag>();
+ do_test<false, void>();
+ do_test<false, void*>();
+ do_test<false, std::in_place_tag(&)(...)>();
+}
\ No newline at end of file
diff --git a/test/libcxx/utilities/utility/utility.inplace/__is_inplace_type.pass.cpp b/test/libcxx/utilities/utility/utility.inplace/__is_inplace_type.pass.cpp
deleted file mode 100644
index bfa4c33..0000000
--- a/test/libcxx/utilities/utility/utility.inplace/__is_inplace_type.pass.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03, c++11, c++14
-
-// <utility>
-
-// template <class Tp>
-// struct __is_inplace_type;
-
-#include <utility>
-#include <cassert>
-
-int main() {
- static_assert(std::__is_inplace_type<std::in_place_t>::value, "");
- static_assert(std::__is_inplace_type<std::in_place_type_t<int>>::value, "");
- static_assert(std::__is_inplace_type<std::in_place_index_t<static_cast<size_t>(-1)>>::value, "");
- static_assert(!std::__is_inplace_type<std::in_place_tag>::value, "");
- static_assert(!std::__is_inplace_type<void*>::value, "");
- static_assert(!std::__is_inplace_type<std::in_place_tag(&)(...)>::value, "");
-}
\ No newline at end of file
diff --git a/test/std/utilities/any/any.class/any.assign/copy.pass.cpp b/test/std/utilities/any/any.class/any.assign/copy.pass.cpp
index fc76a2d..eba9bc6 100644
--- a/test/std/utilities/any/any.class/any.assign/copy.pass.cpp
+++ b/test/std/utilities/any/any.class/any.assign/copy.pass.cpp
@@ -153,7 +153,7 @@
assert(Tp::count == 1);
assertEmpty<Tp>(lhs);
- assertContains<Tp>(rhs);
+ assertContains<Tp>(rhs, 1);
}
{
any lhs((small(2)));
@@ -166,7 +166,7 @@
assert(small::count == 1);
assert(Tp::count == 1);
assertContains<small>(lhs, 2);
- assertContains<Tp>(rhs);
+ assertContains<Tp>(rhs, 1);
}
{
any lhs((large(2)));
@@ -179,7 +179,7 @@
assert(large::count == 1);
assert(Tp::count == 1);
assertContains<large>(lhs, 2);
- assertContains<Tp>(rhs);
+ assertContains<Tp>(rhs, 1);
}
#endif
}
diff --git a/test/std/utilities/any/any.class/any.assign/value.pass.cpp b/test/std/utilities/any/any.class/any.assign/value.pass.cpp
index cb8dd4c..6af4817 100644
--- a/test/std/utilities/any/any.class/any.assign/value.pass.cpp
+++ b/test/std/utilities/any/any.class/any.assign/value.pass.cpp
@@ -172,15 +172,15 @@
// * std::in_place type.
// * Non-copyable types
void test_sfinae_constraints() {
- {
+ { // Only the constructors are required to SFINAE on in_place_t
using Tag = std::in_place_type_t<int>;
using RawTag = std::remove_reference_t<Tag>;
- static_assert(!std::is_assignable<std::any, RawTag&&>::value, "");
+ static_assert(std::is_assignable<std::any, RawTag&&>::value, "");
}
{
struct Dummy { Dummy() = delete; };
using T = std::in_place_type_t<Dummy>;
- static_assert(!std::is_assignable<std::any, T>::value, "");
+ static_assert(std::is_assignable<std::any, T>::value, "");
}
{
// Test that the ValueType&& constructor SFINAE's away when the
diff --git a/test/std/utilities/any/any.class/any.cons/value.pass.cpp b/test/std/utilities/any/any.class/any.cons/value.pass.cpp
index e39f139..24160dc 100644
--- a/test/std/utilities/any/any.class/any.cons/value.pass.cpp
+++ b/test/std/utilities/any/any.class/any.cons/value.pass.cpp
@@ -108,17 +108,12 @@
// Test that any(ValueType&&) is *never* selected for a std::in_place type.
void test_sfinae_constraints() {
- using Tag = std::in_place_type_t<int>;
-#if defined(__clang__)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wignored-qualifiers"
-#endif
- static_assert(std::is_same<Tag, const Tag>::value, "");
-#if defined(__clang__)
-#pragma clang diagnostic pop
-#endif
+ using BadTag = std::in_place_type_t<int>;
+ using OKTag = std::in_place_t;
+ using OKDecay = std::decay_t<OKTag>;
// Test that the tag type is properly handled in SFINAE
- Tag t = std::in_place;
+ BadTag t = std::in_place;
+ OKTag ot = std::in_place;
{
std::any a(t);
assertContains<int>(a, 0);
@@ -128,11 +123,24 @@
assertContains<int>(a, 0);
}
{
+ std::any a(ot);
+ assertContains<OKDecay>(a, ot);
+ }
+ {
+ OKDecay d = ot;
+ std::any a(d);
+ assertContains<OKDecay>(a, ot);
+ }
+ {
struct Dummy { Dummy() = delete; };
using T = std::in_place_type_t<Dummy>;
static_assert(!std::is_constructible<std::any, T>::value, "");
}
{
+ using DecayTag = std::decay_t<BadTag>;
+ static_assert(!std::is_constructible<std::any, DecayTag>::value, "");
+ }
+ {
// Test that the ValueType&& constructor SFINAE's away when the
// argument is non-copyable
struct NoCopy {
diff --git a/test/std/utilities/any/any.class/any.modifiers/reset.pass.cpp b/test/std/utilities/any/any.class/any.modifiers/reset.pass.cpp
index 31648a0..45bc70f 100644
--- a/test/std/utilities/any/any.class/any.modifiers/reset.pass.cpp
+++ b/test/std/utilities/any/any.class/any.modifiers/reset.pass.cpp
@@ -53,7 +53,7 @@
{
any a(large(1));
assert(large::count == 1);
- assertContains<large>(a);
+ assertContains<large>(a, 1);
a.reset();
diff --git a/test/support/any_helpers.h b/test/support/any_helpers.h
index ae332d5..a720ecd 100644
--- a/test/support/any_helpers.h
+++ b/test/support/any_helpers.h
@@ -59,21 +59,30 @@
assert(any_cast<LastType const>(&a) == nullptr);
}
+template <class Type>
+constexpr auto has_value_member(int) -> decltype(std::declval<Type&>().value, true)
+{ return true; }
+template <class> constexpr bool has_value_member(long) { return false; }
+
+
// Assert that an 'any' object stores the specified 'Type' and 'value'.
template <class Type>
-void assertContains(std::any const& a, int value = 1) {
+std::enable_if_t<has_value_member<Type>(0)>
+assertContains(std::any const& a, int value) {
assert(a.has_value());
assert(containsType<Type>(a));
assert(std::any_cast<Type const &>(a).value == value);
}
-template <>
-void assertContains<int>(std::any const& a, int value) {
+template <class Type, class Value>
+std::enable_if_t<!has_value_member<Type>(0)>
+assertContains(std::any const& a, Value value) {
assert(a.has_value());
- assert(containsType<int>(a));
- assert(std::any_cast<int const &>(a) == value);
+ assert(containsType<Type>(a));
+ assert(std::any_cast<Type const &>(a) == value);
}
+
// Modify the value of a "test type" stored within an any to the specified
// 'value'.
template <class Type>
diff --git a/www/upcoming_meeting.html b/www/upcoming_meeting.html
index ec447b1..36c9a74 100644
--- a/www/upcoming_meeting.html
+++ b/www/upcoming_meeting.html
@@ -111,7 +111,7 @@
<tr><td><a href="http://wg21.link/LWG2739">2739</a></td><td>Issue with time_point non-member subtraction with an unsigned duration</td><td>Issaquah</td><td>Patch Ready</td></tr>
<tr><td><a href="http://wg21.link/LWG2740">2740</a></td><td>constexpr optional<T>::operator-></td><td>Issaquah</td><td></td></tr>
<tr><td><a href="http://wg21.link/LWG2742">2742</a></td><td>Inconsistent string interface taking string_view</td><td>Issaquah</td><td>Patch Ready</td></tr>
- <tr><td><a href="http://wg21.link/LWG2744">2744</a></td><td>any's in_place constructors</td><td>Issaquah</td><td></td></tr>
+ <tr><td><a href="http://wg21.link/LWG2744">2744</a></td><td>any's in_place constructors</td><td>Issaquah</td><td>Implemented in trunk</td></tr>
<tr><td><a href="http://wg21.link/LWG2745">2745</a></td><td>[fund.ts.v2] Implementability of LWG 2451</td><td>Issaquah</td><td></td></tr>
<tr><td><a href="http://wg21.link/LWG2747">2747</a></td><td>Possibly redundant std::move in [alg.foreach]</td><td>Issaquah</td><td>Patch ready</td></tr>
<tr><td><a href="http://wg21.link/LWG2748">2748</a></td><td>swappable traits for optionals</td><td>Issaquah</td><td></td></tr>
@@ -189,7 +189,7 @@
<li>2739 - Patch and tests ready</li>
<li>2740 - <i>std::optional</i></li>
<li>2742 - Patch and tests ready</li>
-<li>2744 - <i>std::any</i></li>
+<li>2744 - <i>std::any</i>: We already do this. We also check for a decayed in_place_type_t. </li>
<li>2745 - <i>std::optional</i> for LFTS -- should be considered for C++17</li>
<li>2747 - Patch ready, but I can't think of any way to test it.</li>
<li>2748 - <i>std::optional</i></li>