Update issue status for LWG 2744

llvm-svn: 284322
This commit is contained in:
Eric Fiselier 2016-10-16 02:51:50 +00:00
parent 9c737fddba
commit 50253ed1c6
10 changed files with 93 additions and 60 deletions

View File

@ -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);

View File

@ -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

View File

@ -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(&)(...)>();
}

View File

@ -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, "");
}

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -53,7 +53,7 @@ int main()
{
any a(large(1));
assert(large::count == 1);
assertContains<large>(a);
assertContains<large>(a, 1);
a.reset();

View File

@ -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>

View File

@ -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>