forked from OSchip/llvm-project
parent
9c737fddba
commit
50253ed1c6
|
@ -200,7 +200,7 @@ public:
|
|||
, 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 @@ public:
|
|||
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);
|
||||
|
|
|
@ -928,10 +928,20 @@ inline in_place_tag in_place(__in_place_index_tag<_Nx>) {
|
|||
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
|
||||
|
||||
|
|
|
@ -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(&)(...)>();
|
||||
}
|
|
@ -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, "");
|
||||
}
|
|
@ -153,7 +153,7 @@ void test_copy_assign_throws()
|
|||
|
||||
assert(Tp::count == 1);
|
||||
assertEmpty<Tp>(lhs);
|
||||
assertContains<Tp>(rhs);
|
||||
assertContains<Tp>(rhs, 1);
|
||||
}
|
||||
{
|
||||
any lhs((small(2)));
|
||||
|
@ -166,7 +166,7 @@ void test_copy_assign_throws()
|
|||
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 @@ void test_copy_assign_throws()
|
|||
assert(large::count == 1);
|
||||
assert(Tp::count == 1);
|
||||
assertContains<large>(lhs, 2);
|
||||
assertContains<Tp>(rhs);
|
||||
assertContains<Tp>(rhs, 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -172,15 +172,15 @@ void test_assign_throws() {
|
|||
// * 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
|
||||
|
|
|
@ -108,17 +108,12 @@ void test_copy_move_value() {
|
|||
|
||||
// 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);
|
||||
|
@ -127,11 +122,24 @@ void test_sfinae_constraints() {
|
|||
std::any a(std::move(t));
|
||||
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
|
||||
|
|
|
@ -53,7 +53,7 @@ int main()
|
|||
{
|
||||
any a(large(1));
|
||||
assert(large::count == 1);
|
||||
assertContains<large>(a);
|
||||
assertContains<large>(a, 1);
|
||||
|
||||
a.reset();
|
||||
|
||||
|
|
|
@ -59,21 +59,30 @@ void assertEmpty(std::any const& a) {
|
|||
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>
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue