any (any::operator=(const any&)): Move check for self-assignment.

* include/experimental/any (any::operator=(const any&)): Move check
	for self-assignment.
	(any::operator=(any&&)): Add check for self-assignment.
	(any::operator=(_ValueType&&)): Constrain template argument.
	(any::swap(any&)): Add check for self-swap.
	* testsuite/experimental/any/assign/self.cc: Test move and swap.
	* testsuite/experimental/any/misc/any_cast_neg.cc: Update dg-error.

From-SVN: r226894
This commit is contained in:
Jonathan Wakely 2015-08-14 12:51:18 +01:00 committed by Jonathan Wakely
parent 357c9f7edc
commit 2548a4d6ba
4 changed files with 94 additions and 31 deletions

View File

@ -1,3 +1,13 @@
2015-08-14 Jonathan Wakely <jwakely@redhat.com>
* include/experimental/any (any::operator=(const any&)): Move check
for self-assignment.
(any::operator=(any&&)): Add check for self-assignment.
(any::operator=(_ValueType&&)): Constrain template argument.
(any::swap(any&)): Add check for self-swap.
* testsuite/experimental/any/assign/self.cc: Test move and swap.
* testsuite/experimental/any/misc/any_cast_neg.cc: Update dg-error.
2015-08-14 Jonathan Wakely <jwakely@redhat.com>
* include/experimental/array: Add feature-test macro.

View File

@ -175,12 +175,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Copy the state of another object.
any& operator=(const any& __rhs)
{
if (this == &__rhs)
return *this;
if (__rhs.empty())
clear();
else
else if (this != &__rhs)
{
if (!empty())
_M_manager(_Op_destroy, this, nullptr);
@ -200,7 +197,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
if (__rhs.empty())
clear();
else
else if (this != &__rhs)
{
if (!empty())
_M_manager(_Op_destroy, this, nullptr);
@ -213,7 +210,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Store a copy of @p __rhs as the contained object.
template<typename _ValueType>
any& operator=(_ValueType&& __rhs)
enable_if_t<!is_same<any, decay_t<_ValueType>>::value, any&>
operator=(_ValueType&& __rhs)
{
*this = any(std::forward<_ValueType>(__rhs));
return *this;
@ -233,30 +231,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Exchange state with another object.
void swap(any& __rhs) noexcept
{
if (empty() && __rhs.empty())
return;
{
if (empty() && __rhs.empty())
return;
if (!empty() && !__rhs.empty())
{
any __tmp;
_Arg __arg;
__arg._M_any = &__tmp;
__rhs._M_manager(_Op_xfer, &__rhs, &__arg);
__arg._M_any = &__rhs;
_M_manager(_Op_xfer, this, &__arg);
__arg._M_any = this;
__tmp._M_manager(_Op_xfer, &__tmp, &__arg);
}
else
{
any* __empty = empty() ? this : &__rhs;
any* __full = empty() ? &__rhs : this;
_Arg __arg;
__arg._M_any = __empty;
__full->_M_manager(_Op_xfer, __full, &__arg);
}
}
if (!empty() && !__rhs.empty())
{
if (this == &__rhs)
return;
any __tmp;
_Arg __arg;
__arg._M_any = &__tmp;
__rhs._M_manager(_Op_xfer, &__rhs, &__arg);
__arg._M_any = &__rhs;
_M_manager(_Op_xfer, this, &__arg);
__arg._M_any = this;
__tmp._M_manager(_Op_xfer, &__tmp, &__arg);
}
else
{
any* __empty = empty() ? this : &__rhs;
any* __full = empty() ? &__rhs : this;
_Arg __arg;
__arg._M_any = __empty;
__full->_M_manager(_Op_xfer, __full, &__arg);
}
}
// observers

View File

@ -18,8 +18,17 @@
// { dg-options "-std=gnu++14" }
#include <experimental/any>
#include <set>
#include <testsuite_hooks.h>
std::set<const void*> live_objects;
struct A {
A() { live_objects.insert(this); }
~A() { live_objects.erase(this); }
A(const A& a) { VERIFY(live_objects.count(&a)); live_objects.insert(this); }
};
void
test01()
{
@ -29,13 +38,56 @@ test01()
a = a;
VERIFY( a.empty() );
a = 1;
a = A{};
a = a;
VERIFY( !a.empty() );
a.clear();
VERIFY( live_objects.empty() );
}
void
test02()
{
using std::experimental::any;
struct X {
any a;
};
X x;
std::swap(x, x); // results in "self-move-assignment" of X::a
VERIFY( x.a.empty() );
x.a = A{};
std::swap(x, x); // results in "self-move-assignment" of X::a
VERIFY( !x.a.empty() );
x.a.clear();
VERIFY( live_objects.empty() );
}
void
test03()
{
using std::experimental::any;
any a;
a.swap(a);
VERIFY( a.empty() );
a = A{};
a.swap(a);
VERIFY( !a.empty() );
a.clear();
VERIFY( live_objects.empty() );
}
int
main()
{
test01();
test02();
test03();
}

View File

@ -26,5 +26,5 @@ void test01()
using std::experimental::any_cast;
const any y(1);
any_cast<int&>(y); // { dg-error "qualifiers" "" { target { *-*-* } } 359 }
any_cast<int&>(y); // { dg-error "qualifiers" "" { target { *-*-* } } 360 }
}