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:
parent
357c9f7edc
commit
2548a4d6ba
4 changed files with 94 additions and 31 deletions
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue