+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.
/// 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);
{
if (__rhs.empty())
clear();
- else
+ else if (this != &__rhs)
{
if (!empty())
_M_manager(_Op_destroy, this, nullptr);
/// 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;
/// 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
// { 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()
{
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();
}