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>
|
2015-08-14 Jonathan Wakely <jwakely@redhat.com>
|
||||||
|
|
||||||
* include/experimental/array: Add feature-test macro.
|
* include/experimental/array: Add feature-test macro.
|
||||||
|
|
|
@ -175,12 +175,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
/// Copy the state of another object.
|
/// Copy the state of another object.
|
||||||
any& operator=(const any& __rhs)
|
any& operator=(const any& __rhs)
|
||||||
{
|
{
|
||||||
if (this == &__rhs)
|
|
||||||
return *this;
|
|
||||||
|
|
||||||
if (__rhs.empty())
|
if (__rhs.empty())
|
||||||
clear();
|
clear();
|
||||||
else
|
else if (this != &__rhs)
|
||||||
{
|
{
|
||||||
if (!empty())
|
if (!empty())
|
||||||
_M_manager(_Op_destroy, this, nullptr);
|
_M_manager(_Op_destroy, this, nullptr);
|
||||||
|
@ -200,7 +197,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
{
|
{
|
||||||
if (__rhs.empty())
|
if (__rhs.empty())
|
||||||
clear();
|
clear();
|
||||||
else
|
else if (this != &__rhs)
|
||||||
{
|
{
|
||||||
if (!empty())
|
if (!empty())
|
||||||
_M_manager(_Op_destroy, this, nullptr);
|
_M_manager(_Op_destroy, this, nullptr);
|
||||||
|
@ -213,7 +210,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
|
|
||||||
/// Store a copy of @p __rhs as the contained object.
|
/// Store a copy of @p __rhs as the contained object.
|
||||||
template<typename _ValueType>
|
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));
|
*this = any(std::forward<_ValueType>(__rhs));
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -233,30 +231,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
|
|
||||||
/// Exchange state with another object.
|
/// Exchange state with another object.
|
||||||
void swap(any& __rhs) noexcept
|
void swap(any& __rhs) noexcept
|
||||||
{
|
{
|
||||||
if (empty() && __rhs.empty())
|
if (empty() && __rhs.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!empty() && !__rhs.empty())
|
if (!empty() && !__rhs.empty())
|
||||||
{
|
{
|
||||||
any __tmp;
|
if (this == &__rhs)
|
||||||
_Arg __arg;
|
return;
|
||||||
__arg._M_any = &__tmp;
|
|
||||||
__rhs._M_manager(_Op_xfer, &__rhs, &__arg);
|
any __tmp;
|
||||||
__arg._M_any = &__rhs;
|
_Arg __arg;
|
||||||
_M_manager(_Op_xfer, this, &__arg);
|
__arg._M_any = &__tmp;
|
||||||
__arg._M_any = this;
|
__rhs._M_manager(_Op_xfer, &__rhs, &__arg);
|
||||||
__tmp._M_manager(_Op_xfer, &__tmp, &__arg);
|
__arg._M_any = &__rhs;
|
||||||
}
|
_M_manager(_Op_xfer, this, &__arg);
|
||||||
else
|
__arg._M_any = this;
|
||||||
{
|
__tmp._M_manager(_Op_xfer, &__tmp, &__arg);
|
||||||
any* __empty = empty() ? this : &__rhs;
|
}
|
||||||
any* __full = empty() ? &__rhs : this;
|
else
|
||||||
_Arg __arg;
|
{
|
||||||
__arg._M_any = __empty;
|
any* __empty = empty() ? this : &__rhs;
|
||||||
__full->_M_manager(_Op_xfer, __full, &__arg);
|
any* __full = empty() ? &__rhs : this;
|
||||||
}
|
_Arg __arg;
|
||||||
}
|
__arg._M_any = __empty;
|
||||||
|
__full->_M_manager(_Op_xfer, __full, &__arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// observers
|
// observers
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,17 @@
|
||||||
// { dg-options "-std=gnu++14" }
|
// { dg-options "-std=gnu++14" }
|
||||||
|
|
||||||
#include <experimental/any>
|
#include <experimental/any>
|
||||||
|
#include <set>
|
||||||
#include <testsuite_hooks.h>
|
#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
|
void
|
||||||
test01()
|
test01()
|
||||||
{
|
{
|
||||||
|
@ -29,13 +38,56 @@ test01()
|
||||||
a = a;
|
a = a;
|
||||||
VERIFY( a.empty() );
|
VERIFY( a.empty() );
|
||||||
|
|
||||||
a = 1;
|
a = A{};
|
||||||
a = a;
|
a = a;
|
||||||
VERIFY( !a.empty() );
|
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
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
test01();
|
test01();
|
||||||
|
test02();
|
||||||
|
test03();
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,5 +26,5 @@ void test01()
|
||||||
using std::experimental::any_cast;
|
using std::experimental::any_cast;
|
||||||
|
|
||||||
const any y(1);
|
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