[libcxx] Add <experimental/any> v2.

Summary:
This patch adds the second revision of <experimental/any>. 
I've been working from the LFTS draft found at this link. https://rawgit.com/cplusplus/fundamentals-ts/v1/fundamentals-ts.html#any



Reviewers: danalbert, jroelofs, K-ballo, mclow.lists

Subscribers: cfe-commits

Differential Revision: http://reviews.llvm.org/D6762

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@243728 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eric Fiselier
2015-07-31 02:24:58 +00:00
parent 26d2390a8d
commit 7175a07921
28 changed files with 2873 additions and 0 deletions

View File

@@ -0,0 +1,197 @@
//===----------------------------------------------------------------------===//
//
// 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
// <experimental/any>
// any& operator=(any const &);
// Test copy assignment
#include <experimental/any>
#include <cassert>
#include "any_helpers.h"
#include "count_new.hpp"
#include "test_macros.h"
using std::experimental::any;
using std::experimental::any_cast;
template <class LHS, class RHS>
void test_copy_assign() {
assert(LHS::count == 0);
assert(RHS::count == 0);
LHS::reset();
RHS::reset();
{
any lhs(LHS(1));
any const rhs(RHS(2));
assert(LHS::count == 1);
assert(RHS::count == 1);
assert(RHS::copied == 0);
lhs = rhs;
assert(RHS::copied == 1);
assert(LHS::count == 0);
assert(RHS::count == 2);
assertContains<RHS>(lhs, 2);
assertContains<RHS>(rhs, 2);
}
assert(LHS::count == 0);
assert(RHS::count == 0);
}
template <class LHS>
void test_copy_assign_empty() {
assert(LHS::count == 0);
LHS::reset();
{
any lhs;
any const rhs(LHS(42));
assert(LHS::count == 1);
assert(LHS::copied == 0);
lhs = rhs;
assert(LHS::copied == 1);
assert(LHS::count == 2);
assertContains<LHS>(lhs, 42);
assertContains<LHS>(rhs, 42);
}
assert(LHS::count == 0);
LHS::reset();
{
any lhs(LHS(1));
any const rhs;
assert(LHS::count == 1);
assert(LHS::copied == 0);
lhs = rhs;
assert(LHS::copied == 0);
assert(LHS::count == 0);
assertEmpty<LHS>(lhs);
assertEmpty(rhs);
}
assert(LHS::count == 0);
}
void test_copy_assign_self() {
// empty
{
any a;
a = a;
assertEmpty(a);
assert(globalMemCounter.checkOutstandingNewEq(0));
}
assert(globalMemCounter.checkOutstandingNewEq(0));
// small
{
any a((small(1)));
assert(small::count == 1);
a = a;
assert(small::count == 1);
assertContains<small>(a, 1);
assert(globalMemCounter.checkOutstandingNewEq(0));
}
assert(small::count == 0);
assert(globalMemCounter.checkOutstandingNewEq(0));
// large
{
any a(large(1));
assert(large::count == 1);
a = a;
assert(large::count == 1);
assertContains<large>(a, 1);
assert(globalMemCounter.checkOutstandingNewEq(1));
}
assert(large::count == 0);
assert(globalMemCounter.checkOutstandingNewEq(0));
}
template <class Tp>
void test_copy_assign_throws()
{
#if !defined(TEST_HAS_NO_EXCEPTIONS)
auto try_throw =
[](any& lhs, any const& rhs) {
try {
lhs = rhs;
assert(false);
} catch (my_any_exception const &) {
// do nothing
} catch (...) {
assert(false);
}
};
// const lvalue to empty
{
any lhs;
any const rhs((Tp(1)));
assert(Tp::count == 1);
try_throw(lhs, rhs);
assert(Tp::count == 1);
assertEmpty<Tp>(lhs);
assertContains<Tp>(rhs);
}
{
any lhs((small(2)));
any const rhs((Tp(1)));
assert(small::count == 1);
assert(Tp::count == 1);
try_throw(lhs, rhs);
assert(small::count == 1);
assert(Tp::count == 1);
assertContains<small>(lhs, 2);
assertContains<Tp>(rhs);
}
{
any lhs((large(2)));
any const rhs((Tp(1)));
assert(large::count == 1);
assert(Tp::count == 1);
try_throw(lhs, rhs);
assert(large::count == 1);
assert(Tp::count == 1);
assertContains<large>(lhs, 2);
assertContains<Tp>(rhs);
}
#endif
}
int main() {
test_copy_assign<small1, small2>();
test_copy_assign<large1, large2>();
test_copy_assign<small, large>();
test_copy_assign<large, small>();
test_copy_assign_empty<small>();
test_copy_assign_empty<large>();
test_copy_assign_self();
test_copy_assign_throws<small_throws_on_copy>();
test_copy_assign_throws<large_throws_on_copy>();
}

View File

@@ -0,0 +1,102 @@
//===----------------------------------------------------------------------===//
//
// 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
// <experimental/any>
// any& operator=(any &&);
// Test move assignment.
#include <experimental/any>
#include <cassert>
#include "any_helpers.h"
#include "test_macros.h"
using std::experimental::any;
using std::experimental::any_cast;
template <class LHS, class RHS>
void test_move_assign() {
assert(LHS::count == 0);
assert(RHS::count == 0);
{
LHS const s1(1);
any a(s1);
RHS const s2(2);
any a2(s2);
assert(LHS::count == 2);
assert(RHS::count == 2);
a = std::move(a2);
assert(LHS::count == 1);
assert(RHS::count == 2);
assertContains<RHS>(a, 2);
assertEmpty<RHS>(a2);
}
assert(LHS::count == 0);
assert(RHS::count == 0);
}
template <class LHS>
void test_move_assign_empty() {
assert(LHS::count == 0);
{
any a;
any a2((LHS(1)));
assert(LHS::count == 1);
a = std::move(a2);
assert(LHS::count == 1);
assertContains<LHS>(a, 1);
assertEmpty<LHS>(a2);
}
assert(LHS::count == 0);
{
any a((LHS(1)));
any a2;
assert(LHS::count == 1);
a = std::move(a2);
assert(LHS::count == 0);
assertEmpty<LHS>(a);
assertEmpty(a2);
}
assert(LHS::count == 0);
}
void test_move_assign_noexcept() {
any a1;
any a2;
static_assert(
noexcept(a1 = std::move(a2))
, "any & operator=(any &&) must be noexcept"
);
}
int main() {
test_move_assign_noexcept();
test_move_assign<small1, small2>();
test_move_assign<large1, large2>();
test_move_assign<small, large>();
test_move_assign<large, small>();
test_move_assign_empty<small>();
test_move_assign_empty<large>();
}

View File

@@ -0,0 +1,177 @@
//===----------------------------------------------------------------------===//
//
// 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
// <experimental/any>
// any& operator=(any const &);
// Test value copy and move assignment.
#include <experimental/any>
#include <cassert>
#include "any_helpers.h"
#include "count_new.hpp"
#include "test_macros.h"
using std::experimental::any;
using std::experimental::any_cast;
template <class LHS, class RHS>
void test_assign_value() {
assert(LHS::count == 0);
assert(RHS::count == 0);
LHS::reset();
RHS::reset();
{
any lhs(LHS(1));
any const rhs(RHS(2));
assert(LHS::count == 1);
assert(RHS::count == 1);
assert(RHS::copied == 0);
lhs = rhs;
assert(RHS::copied == 1);
assert(LHS::count == 0);
assert(RHS::count == 2);
assertContains<RHS>(lhs, 2);
assertContains<RHS>(rhs, 2);
}
assert(LHS::count == 0);
assert(RHS::count == 0);
LHS::reset();
RHS::reset();
{
any lhs(LHS(1));
any rhs(RHS(2));
assert(LHS::count == 1);
assert(RHS::count == 1);
assert(RHS::moved == 1);
lhs = std::move(rhs);
assert(RHS::moved >= 1);
assert(RHS::copied == 0);
assert(LHS::count == 0);
assert(RHS::count == 1);
assertContains<RHS>(lhs, 2);
assertEmpty<RHS>(rhs);
}
assert(LHS::count == 0);
assert(RHS::count == 0);
}
template <class RHS>
void test_assign_value_empty() {
assert(RHS::count == 0);
RHS::reset();
{
any lhs;
RHS rhs(42);
assert(RHS::count == 1);
assert(RHS::copied == 0);
lhs = rhs;
assert(RHS::count == 2);
assert(RHS::copied == 1);
assert(RHS::moved >= 0);
assertContains<RHS>(lhs, 42);
}
assert(RHS::count == 0);
RHS::reset();
{
any lhs;
RHS rhs(42);
assert(RHS::count == 1);
assert(RHS::moved == 0);
lhs = std::move(rhs);
assert(RHS::count == 2);
assert(RHS::copied == 0);
assert(RHS::moved >= 1);
assertContains<RHS>(lhs, 42);
}
assert(RHS::count == 0);
RHS::reset();
}
template <class Tp, bool Move = false>
void test_assign_throws() {
#if !defined(TEST_HAS_NO_EXCEPTIONS)
auto try_throw=
[](any& lhs, auto&& rhs) {
try {
Move ? lhs = std::move(rhs)
: lhs = rhs;
assert(false);
} catch (my_any_exception const &) {
// do nothing
} catch (...) {
assert(false);
}
};
// const lvalue to empty
{
any lhs;
Tp rhs(1);
assert(Tp::count == 1);
try_throw(lhs, rhs);
assert(Tp::count == 1);
assertEmpty<Tp>(lhs);
}
{
any lhs((small(2)));
Tp rhs(1);
assert(small::count == 1);
assert(Tp::count == 1);
try_throw(lhs, rhs);
assert(small::count == 1);
assert(Tp::count == 1);
assertContains<small>(lhs, 2);
}
{
any lhs((large(2)));
Tp rhs(1);
assert(large::count == 1);
assert(Tp::count == 1);
try_throw(lhs, rhs);
assert(large::count == 1);
assert(Tp::count == 1);
assertContains<large>(lhs, 2);
}
#endif
}
int main() {
test_assign_value<small1, small2>();
test_assign_value<large1, large2>();
test_assign_value<small, large>();
test_assign_value<large, small>();
test_assign_value_empty<small>();
test_assign_value_empty<large>();
test_assign_throws<small_throws_on_copy>();
test_assign_throws<large_throws_on_copy>();
test_assign_throws<throws_on_move, /* Move = */ true>();
}

View File

@@ -0,0 +1,38 @@
//===----------------------------------------------------------------------===//
//
// 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
// <experimental/any>
// template <class Value>
// any& operator=(Value &&);
// Instantiate the value assignment operator with a non-copyable type.
#include <experimental/any>
class non_copyable
{
non_copyable(non_copyable const &);
public:
non_copyable() {}
non_copyable(non_copyable &&) {}
};
int main()
{
using namespace std::experimental;
non_copyable nc;
any a;
a = static_cast<non_copyable &&>(nc); // expected-error@experimental/any:* 2 {{static_assert failed "_ValueType must be CopyConstructible."}}
// expected-error@experimental/any:* {{calling a private constructor of class 'non_copyable'}}
}

View File

@@ -0,0 +1,100 @@
//===----------------------------------------------------------------------===//
//
// 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
// <experimental/any>
// any(any const &);
#include <experimental/any>
#include <cassert>
#include "any_helpers.h"
#include "count_new.hpp"
#include "test_macros.h"
using std::experimental::any;
using std::experimental::any_cast;
template <class Type>
void test_copy_throws() {
#if !defined(TEST_HAS_NO_EXCEPTIONS)
assert(Type::count == 0);
{
any const a((Type(42)));
assert(Type::count == 1);
try {
any const a2(a);
assert(false);
} catch (my_any_exception const &) {
// do nothing
} catch (...) {
assert(false);
}
assert(Type::count == 1);
assertContains<Type>(a, 42);
}
assert(Type::count == 0);
#endif
}
void test_copy_empty() {
DisableAllocationGuard g; ((void)g); // No allocations should occur.
any a1;
any a2(a1);
assertEmpty(a1);
assertEmpty(a2);
}
template <class Type>
void test_copy()
{
// Copying small types should not perform any allocations.
DisableAllocationGuard g(isSmallType<Type>()); ((void)g);
assert(Type::count == 0);
Type::reset();
{
any a((Type(42)));
assert(Type::count == 1);
assert(Type::copied == 0);
any a2(a);
assert(Type::copied == 1);
assert(Type::count == 2);
assertContains<Type>(a, 42);
assertContains<Type>(a, 42);
// Modify a and check that a2 is unchanged
modifyValue<Type>(a, -1);
assertContains<Type>(a, -1);
assertContains<Type>(a2, 42);
// modify a2 and check that a is unchanged
modifyValue<Type>(a2, 999);
assertContains<Type>(a, -1);
assertContains<Type>(a2, 999);
// clear a and check that a2 is unchanged
a.clear();
assertEmpty(a);
assertContains<Type>(a2, 999);
}
assert(Type::count == 0);
}
int main() {
test_copy<small>();
test_copy<large>();
test_copy_empty();
test_copy_throws<small_throws_on_copy>();
test_copy_throws<large_throws_on_copy>();
}

View File

@@ -0,0 +1,38 @@
//===----------------------------------------------------------------------===//
//
// 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
// <experimental/any>
// any() noexcept;
#include <experimental/any>
#include <type_traits>
#include <cassert>
#include "any_helpers.h"
#include "count_new.hpp"
int main()
{
using std::experimental::any;
{
static_assert(
std::is_nothrow_default_constructible<any>::value
, "Must be default constructible"
);
}
{
DisableAllocationGuard g; ((void)g);
any const a;
assertEmpty(a);
}
}

View File

@@ -0,0 +1,102 @@
//===----------------------------------------------------------------------===//
//
// 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
// <experimental/any>
// any(any &&) noexcept;
#include <experimental/any>
#include <utility>
#include <type_traits>
#include <cassert>
#include "any_helpers.h"
#include "count_new.hpp"
#include "test_macros.h"
using std::experimental::any;
using std::experimental::any_cast;
// Moves are always noexcept. The throws_on_move object
// must be stored dynamically so the pointer is moved and
// not the stored object.
void test_move_does_not_throw()
{
#if !defined(TEST_HAS_NO_EXCEPTIONS)
assert(throws_on_move::count == 0);
{
throws_on_move v(42);
any a(v);
assert(throws_on_move::count == 2);
// No allocations should be performed after this point.
DisableAllocationGuard g; ((void)g);
try {
any const a2(std::move(a));
assertEmpty(a);
assertContains<throws_on_move>(a2, 42);
} catch (...) {
assert(false);
}
assert(throws_on_move::count == 1);
assertEmpty(a);
}
assert(throws_on_move::count == 0);
#endif
}
void test_move_empty() {
DisableAllocationGuard g; ((void)g); // no allocations should be performed.
any a1;
any a2(std::move(a1));
assertEmpty(a1);
assertEmpty(a2);
}
template <class Type>
void test_move() {
assert(Type::count == 0);
Type::reset();
{
any a((Type(42)));
assert(Type::count == 1);
assert(Type::copied == 0);
assert(Type::moved == 1);
// Moving should not perform allocations since it must be noexcept.
DisableAllocationGuard g; ((void)g);
any a2(std::move(a));
assert(Type::moved >= 1); // zero or more move operations can be performed.
assert(Type::copied == 0); // no copies can be performed.
assert(Type::count == 1);
assertEmpty(a); // Moves are always destructive.
assertContains<Type>(a2, 42);
}
assert(Type::count == 0);
}
int main()
{
// noexcept test
{
static_assert(
std::is_nothrow_move_constructible<any>::value
, "any must be nothrow move constructible"
);
}
test_move<small>();
test_move<large>();
test_move_empty();
test_move_does_not_throw();
}

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
// <experimental/any>
// any::any<Value>(Value &&)
// Attempt to construct any with a non-copyable type.
#include <experimental/any>
class non_copyable
{
non_copyable(non_copyable const &);
public:
non_copyable() {}
non_copyable(non_copyable &&) {}
};
int main()
{
using namespace std::experimental;
non_copyable nc;
any a(static_cast<non_copyable &&>(nc));
// expected-error@experimental/any:* 1 {{static_assert failed "_ValueType must be CopyConstructible."}}
// expected-error@experimental/any:* 1 {{calling a private constructor of class 'non_copyable'}}
}

View File

@@ -0,0 +1,116 @@
//===----------------------------------------------------------------------===//
//
// 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
// <experimental/any>
// template <class Value> any(Value &&)
// Test construction from a value.
// Concerns:
// ---------
// 1. The value is properly move/copied depending on the value category.
// 2. Both small and large values are properly handled.
#include <experimental/any>
#include <cassert>
#include "any_helpers.h"
#include "count_new.hpp"
#include "test_macros.h"
using std::experimental::any;
using std::experimental::any_cast;
template <class Type>
void test_copy_value_throws()
{
#if !defined(TEST_HAS_NO_EXCEPTIONS)
assert(Type::count == 0);
{
Type const t(42);
assert(Type::count == 1);
try {
any const a2(t);
assert(false);
} catch (my_any_exception const &) {
// do nothing
} catch (...) {
assert(false);
}
assert(Type::count == 1);
assert(t.value == 42);
}
assert(Type::count == 0);
#endif
}
void test_move_value_throws()
{
#if !defined(TEST_HAS_NO_EXCEPTIONS)
assert(throws_on_move::count == 0);
{
throws_on_move v;
assert(throws_on_move::count == 1);
try {
any const a(std::move(v));
assert(false);
} catch (my_any_exception const &) {
// do nothing
} catch (...) {
assert(false);
}
assert(throws_on_move::count == 1);
}
assert(throws_on_move::count == 0);
#endif
}
template <class Type>
void test_copy_move_value() {
// constructing from a small type should perform no allocations.
DisableAllocationGuard g(isSmallType<Type>()); ((void)g);
assert(Type::count == 0);
Type::reset();
{
Type t(42);
assert(Type::count == 1);
any a(t);
assert(Type::count == 2);
assert(Type::copied == 1);
assert(Type::moved == 0);
assertContains<Type>(a, 42);
}
assert(Type::count == 0);
Type::reset();
{
Type t(42);
assert(Type::count == 1);
any a(std::move(t));
assert(Type::count == 2);
assert(Type::copied == 0);
assert(Type::moved == 1);
assertContains<Type>(a, 42);
}
}
int main() {
test_copy_move_value<small>();
test_copy_move_value<large>();
test_copy_value_throws<small_throws_on_copy>();
test_copy_value_throws<large_throws_on_copy>();
test_move_value_throws();
}

View File

@@ -0,0 +1,63 @@
//===----------------------------------------------------------------------===//
//
// 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
// <experimental/any>
// any::clear() noexcept
#include <experimental/any>
#include <cassert>
#include "any_helpers.h"
int main()
{
using std::experimental::any;
using std::experimental::any_cast;
// empty
{
any a;
// noexcept check
static_assert(
noexcept(a.clear())
, "any.clear() must be noexcept"
);
assertEmpty(a);
a.clear();
assertEmpty(a);
}
// small object
{
any a((small(1)));
assert(small::count == 1);
assertContains<small>(a, 1);
a.clear();
assertEmpty<small>(a);
assert(small::count == 0);
}
// large object
{
any a(large(1));
assert(large::count == 1);
assertContains<large>(a);
a.clear();
assertEmpty<large>(a);
assert(large::count == 0);
}
}

View File

@@ -0,0 +1,101 @@
//===----------------------------------------------------------------------===//
//
// 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
// <experimental/any>
// any::swap(any &) noexcept
// Test swap(large, small) and swap(small, large)
#include <experimental/any>
#include <cassert>
#include "any_helpers.h"
using std::experimental::any;
using std::experimental::any_cast;
template <class LHS, class RHS>
void test_swap() {
assert(LHS::count == 0);
assert(RHS::count == 0);
{
any a1((LHS(1)));
any a2(RHS{2});
assert(LHS::count == 1);
assert(RHS::count == 1);
a1.swap(a2);
assert(LHS::count == 1);
assert(RHS::count == 1);
assertContains<RHS>(a1, 2);
assertContains<LHS>(a2, 1);
}
assert(LHS::count == 0);
assert(RHS::count == 0);
assert(LHS::copied == 0);
assert(RHS::copied == 0);
}
template <class Tp>
void test_swap_empty() {
assert(Tp::count == 0);
{
any a1((Tp(1)));
any a2;
assert(Tp::count == 1);
a1.swap(a2);
assert(Tp::count == 1);
assertContains<Tp>(a2, 1);
assertEmpty(a1);
}
assert(Tp::count == 0);
{
any a1((Tp(1)));
any a2;
assert(Tp::count == 1);
a2.swap(a1);
assert(Tp::count == 1);
assertContains<Tp>(a2, 1);
assertEmpty(a1);
}
assert(Tp::count == 0);
assert(Tp::copied == 0);
}
void test_noexcept()
{
any a1;
any a2;
static_assert(
noexcept(a1.swap(a2))
, "any::swap(any&) must be noexcept"
);
}
int main()
{
test_noexcept();
test_swap_empty<small>();
test_swap_empty<large>();
test_swap<small1, small2>();
test_swap<large1, large2>();
test_swap<small, large>();
test_swap<large, small>();
}

View File

@@ -0,0 +1,64 @@
//===----------------------------------------------------------------------===//
//
// 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
// <experimental/any>
// any::empty() noexcept
#include <experimental/any>
#include <cassert>
#include "any_helpers.h"
int main()
{
using std::experimental::any;
// noexcept test
{
any a;
static_assert(noexcept(a.empty()), "any::empty() must be noexcept");
}
// empty
{
any a;
assert(a.empty());
a.clear();
assert(a.empty());
a = 42;
assert(!a.empty());
}
// small object
{
small const s(1);
any a(s);
assert(!a.empty());
a.clear();
assert(a.empty());
a = s;
assert(!a.empty());
}
// large object
{
large const l(1);
any a(l);
assert(!a.empty());
a.clear();
assert(a.empty());
a = l;
assert(!a.empty());
}
}

View File

@@ -0,0 +1,41 @@
//===----------------------------------------------------------------------===//
//
// 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
// XFAIL: libcpp-no-rtti
// <experimental/any>
// any::type() noexcept
#include <experimental/any>
#include <cassert>
#include "any_helpers.h"
int main()
{
using std::experimental::any;
{
any const a;
assert(a.type() == typeid(void));
static_assert(noexcept(a.type()), "any::type() must be noexcept");
}
{
small const s(1);
any const a(s);
assert(a.type() == typeid(small));
}
{
large const l(1);
any const a(l);
assert(a.type() == typeid(large));
}
}

View File

@@ -0,0 +1,12 @@
//===----------------------------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
#include <experimental/string_view>
int main () {}

View File

@@ -0,0 +1,146 @@
//===----------------------------------------------------------------------===//
//
// 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
// <experimental/any>
// template <class ValueType>
// ValueType const* any_cast(any const *) noexcept;
//
// template <class ValueType>
// ValueType * any_cast(any *) noexcept;
#include <experimental/any>
#include <type_traits>
#include <cassert>
#include "any_helpers.h"
using std::experimental::any;
using std::experimental::any_cast;
// Test that the operators are properly noexcept.
void test_cast_is_noexcept() {
any a;
static_assert(noexcept(any_cast<int>(&a)), "");
any const& ca = a;
static_assert(noexcept(any_cast<int>(&ca)), "");
}
// Test that the return type of any_cast is correct.
void test_cast_return_type() {
any a;
static_assert(std::is_same<decltype(any_cast<int>(&a)), int*>::value, "");
static_assert(std::is_same<decltype(any_cast<int const>(&a)), int const*>::value, "");
any const& ca = a;
static_assert(std::is_same<decltype(any_cast<int>(&ca)), int const*>::value, "");
static_assert(std::is_same<decltype(any_cast<int const>(&ca)), int const*>::value, "");
}
// Test that any_cast handles null pointers.
void test_cast_nullptr() {
any* a = nullptr;
assert(nullptr == any_cast<int>(a));
assert(nullptr == any_cast<int const>(a));
any const* ca = nullptr;
assert(nullptr == any_cast<int>(ca));
assert(nullptr == any_cast<int const>(ca));
}
// Test casting an empty object.
void test_cast_empty() {
{
any a;
assert(nullptr == any_cast<int>(&a));
assert(nullptr == any_cast<int const>(&a));
any const& ca = a;
assert(nullptr == any_cast<int>(&ca));
assert(nullptr == any_cast<int const>(&ca));
}
// Create as non-empty, then make empty and run test.
{
any a(42);
a.clear();
assert(nullptr == any_cast<int>(&a));
assert(nullptr == any_cast<int const>(&a));
any const& ca = a;
assert(nullptr == any_cast<int>(&ca));
assert(nullptr == any_cast<int const>(&ca));
}
}
template <class Type>
void test_cast() {
assert(Type::count == 0);
Type::reset();
{
any a((Type(42)));
any const& ca = a;
assert(Type::count == 1);
assert(Type::copied == 0);
assert(Type::moved == 1);
// Try a cast to a bad type.
// NOTE: Type cannot be an int.
assert(any_cast<int>(&a) == nullptr);
assert(any_cast<int const>(&a) == nullptr);
assert(any_cast<int const volatile>(&a) == nullptr);
// Try a cast to the right type, but as a pointer.
assert(any_cast<Type*>(&a) == nullptr);
assert(any_cast<Type const*>(&a) == nullptr);
// Check getting a unqualified type from a non-const any.
Type* v = any_cast<Type>(&a);
assert(v != nullptr);
assert(v->value == 42);
// change the stored value and later check for the new value.
v->value = 999;
// Check getting a const qualified type from a non-const any.
Type const* cv = any_cast<Type const>(&a);
assert(cv != nullptr);
assert(cv == v);
assert(cv->value == 999);
// Check getting a unqualified type from a const any.
cv = any_cast<Type>(&ca);
assert(cv != nullptr);
assert(cv == v);
assert(cv->value == 999);
// Check getting a const-qualified type from a const any.
cv = any_cast<Type const>(&ca);
assert(cv != nullptr);
assert(cv == v);
assert(cv->value == 999);
// Check that no more objects were created, copied or moved.
assert(Type::count == 1);
assert(Type::copied == 0);
assert(Type::moved == 1);
}
assert(Type::count == 0);
}
int main() {
test_cast_is_noexcept();
test_cast_return_type();
test_cast_nullptr();
test_cast_empty();
test_cast<small>();
test_cast<large>();
}

View File

@@ -0,0 +1,309 @@
//===----------------------------------------------------------------------===//
//
// 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
// <experimental/any>
// template <class ValueType>
// ValueType const any_cast(any const&);
//
// template <class ValueType>
// ValueType any_cast(any &);
//
// template <class ValueType>
// ValueType any_cast(any &&);
#include <experimental/any>
#include <type_traits>
#include <cassert>
#include "any_helpers.h"
#include "count_new.hpp"
#include "test_macros.h"
using std::experimental::any;
using std::experimental::any_cast;
using std::experimental::bad_any_cast;
// Test that the operators are NOT marked noexcept.
void test_cast_is_not_noexcept() {
any a;
static_assert(!noexcept(any_cast<int>(static_cast<any&>(a))), "");
static_assert(!noexcept(any_cast<int>(static_cast<any const&>(a))), "");
static_assert(!noexcept(any_cast<int>(static_cast<any &&>(a))), "");
}
// Test that the return type of any_cast is correct.
void test_cast_return_type() {
any a;
static_assert(std::is_same<decltype(any_cast<int>(a)), int>::value, "");
static_assert(std::is_same<decltype(any_cast<int const>(a)), int>::value, "");
static_assert(std::is_same<decltype(any_cast<int&>(a)), int&>::value, "");
static_assert(std::is_same<decltype(any_cast<int const&>(a)), int const&>::value, "");
//static_assert(std::is_same<decltype(any_cast<int&&>(a)), int&&>::value, "");
//static_assert(std::is_same<decltype(any_cast<int const&&>(a)), int const&&>::value, "");
static_assert(std::is_same<decltype(any_cast<int>(std::move(a))), int>::value, "");
static_assert(std::is_same<decltype(any_cast<int const>(std::move(a))), int>::value, "");
static_assert(std::is_same<decltype(any_cast<int&>(std::move(a))), int&>::value, "");
static_assert(std::is_same<decltype(any_cast<int const&>(std::move(a))), int const&>::value, "");
//static_assert(std::is_same<decltype(any_cast<int&&>(std::move(a))), int&&>::value, "");
//static_assert(std::is_same<decltype(any_cast<int const&&>(std::move(a))), int const&&>::value, "");
any const& ca = a;
static_assert(std::is_same<decltype(any_cast<int>(ca)), int>::value, "");
static_assert(std::is_same<decltype(any_cast<int const>(ca)), int>::value, "");
static_assert(std::is_same<decltype(any_cast<int const&>(ca)), int const&>::value, "");
//static_assert(std::is_same<decltype(any_cast<int const&&>(ca)), int const&&>::value, "");
}
template <class Type, class ConstT = Type>
void checkThrows(any& a)
{
#if !defined(TEST_HAS_NO_EXCEPTIONS)
try {
any_cast<Type>(a);
assert(false);
} catch (bad_any_cast const &) {
// do nothing
} catch (...) {
assert(false);
}
try {
any_cast<ConstT>(static_cast<any const&>(a));
assert(false);
} catch (bad_any_cast const &) {
// do nothing
} catch (...) {
assert(false);
}
try {
any_cast<Type>(static_cast<any&&>(a));
assert(false);
} catch (bad_any_cast const &) {
// do nothing
} catch (...) {
assert(false);
}
#endif
}
void test_cast_empty() {
// None of these operations should allocate.
DisableAllocationGuard g; ((void)g);
any a;
checkThrows<int>(a);
}
template <class Type>
void test_cast_to_reference() {
assert(Type::count == 0);
Type::reset();
{
any a((Type(42)));
any const& ca = a;
assert(Type::count == 1);
assert(Type::copied == 0);
assert(Type::moved == 1);
// Try a cast to a bad type.
// NOTE: Type cannot be an int.
checkThrows<int>(a);
checkThrows<int&, int const&>(a);
checkThrows<Type*, Type const*>(a);
checkThrows<Type const*>(a);
// Check getting a type by reference from a non-const lvalue any.
{
Type& v = any_cast<Type&>(a);
assert(v.value == 42);
Type const &cv = any_cast<Type const&>(a);
assert(&cv == &v);
}
// Check getting a type by reference from a const lvalue any.
{
Type const& v = any_cast<Type const&>(ca);
assert(v.value == 42);
Type const &cv = any_cast<Type const&>(ca);
assert(&cv == &v);
}
// Check getting a type by reference from a non-const rvalue
{
Type& v = any_cast<Type&>(std::move(a));
assert(v.value == 42);
Type const &cv = any_cast<Type const&>(std::move(a));
assert(&cv == &v);
}
// Check getting a type by reference from a const rvalue any.
{
Type const& v = any_cast<Type const&>(std::move(ca));
assert(v.value == 42);
Type const &cv = any_cast<Type const&>(std::move(ca));
assert(&cv == &v);
}
// Check that the original object hasn't been changed.
assertContains<Type>(a, 42);
// Check that no objects have been created/copied/moved.
assert(Type::count == 1);
assert(Type::copied == 0);
assert(Type::moved == 1);
}
assert(Type::count == 0);
}
template <class Type>
void test_cast_to_value() {
assert(Type::count == 0);
Type::reset();
{
any a((Type(42)));
any const& ca = a;
assert(Type::count == 1);
assert(Type::copied == 0);
assert(Type::moved == 1);
// Try a cast to a bad type.
// NOTE: Type cannot be an int.
checkThrows<int>(a);
checkThrows<int&, int const&>(a);
checkThrows<Type*, Type const*>(a);
checkThrows<Type const*>(a);
Type::reset(); // NOTE: reset does not modify Type::count
// Check getting Type by value from a non-const lvalue any.
// This should cause the non-const copy constructor to be called.
{
Type t = any_cast<Type>(a);
assert(Type::count == 2);
assert(Type::copied == 1);
assert(Type::const_copied == 0);
assert(Type::non_const_copied == 1);
assert(Type::moved == 0);
assert(t.value == 42);
}
assert(Type::count == 1);
Type::reset();
// Check getting const Type by value from a non-const lvalue any.
// This should cause the const copy constructor to be called.
{
Type t = any_cast<Type const>(a);
assert(Type::count == 2);
assert(Type::copied == 1);
assert(Type::const_copied == 1);
assert(Type::non_const_copied == 0);
assert(Type::moved == 0);
assert(t.value == 42);
}
assert(Type::count == 1);
Type::reset();
// Check getting Type by value from a non-const lvalue any.
// This should cause the const copy constructor to be called.
{
Type t = any_cast<Type>(static_cast<any const&>(a));
assert(Type::count == 2);
assert(Type::copied == 1);
assert(Type::const_copied == 1);
assert(Type::non_const_copied == 0);
assert(Type::moved == 0);
assert(t.value == 42);
}
assert(Type::count == 1);
Type::reset();
// Check getting Type by value from a non-const rvalue any.
// This should cause the non-const copy constructor to be called.
{
Type t = any_cast<Type>(static_cast<any &&>(a));
assert(Type::count == 2);
assert(Type::copied == 1);
assert(Type::const_copied == 0);
assert(Type::non_const_copied == 1);
assert(Type::moved == 0);
assert(t.value == 42);
}
assert(Type::count == 1);
Type::reset();
// Check getting const Type by value from a non-const rvalue any.
// This should cause the const copy constructor to be called.
{
Type t = any_cast<Type const>(static_cast<any &&>(a));
assert(Type::count == 2);
assert(Type::copied == 1);
assert(Type::const_copied == 1);
assert(Type::non_const_copied == 0);
assert(Type::moved == 0);
assert(t.value == 42);
}
assert(Type::count == 1);
Type::reset();
// Check getting Type by value from a const rvalue any.
// This should cause the const copy constructor to be called.
{
Type t = any_cast<Type>(static_cast<any const&&>(a));
assert(Type::count == 2);
assert(Type::copied == 1);
assert(Type::const_copied == 1);
assert(Type::non_const_copied == 0);
assert(Type::moved == 0);
assert(t.value == 42);
}
// Ensure we still only have 1 Type object alive.
assert(Type::count == 1);
// Check that the original object hasn't been changed.
assertContains<Type>(a, 42);
}
assert(Type::count == 0);
}
// Even though you can't get a non-copyable class into std::any
// the standard requires that these overloads compile and function.
void test_non_copyable_ref() {
struct no_copy
{
no_copy() {}
no_copy(no_copy &&) {}
private:
no_copy(no_copy const &);
};
any a;
checkThrows<no_copy &, no_copy const&>(a);
checkThrows<no_copy const&>(a);
assertEmpty(a);
}
int main() {
test_cast_is_not_noexcept();
test_cast_return_type();
test_cast_empty();
test_cast_to_reference<small>();
test_cast_to_reference<large>();
test_cast_to_value<small>();
test_cast_to_value<large>();
test_non_copyable_ref();
}

View File

@@ -0,0 +1,38 @@
//===----------------------------------------------------------------------===//
//
// 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
// <experimental/any>
// template <class ValueType>
// ValueType any_cast(any const &);
// Try and cast away const.
#include <experimental/any>
struct TestType {};
struct TestType2 {};
int main()
{
using std::experimental::any;
using std::experimental::any_cast;
any a;
// expected-error@experimental/any:* 2 {{binding value of type '_Tp' (aka 'const TestType') to reference to type 'TestType' drops 'const' qualifier}}
any_cast<TestType &>(static_cast<any const&>(a)); // expected-note {{requested here}}
any_cast<TestType &&>(static_cast<any const&>(a)); // expected-note {{requested here}}
// expected-error@experimental/any:* 2 {{binding value of type '_Tp' (aka 'const TestType2') to reference to type 'TestType2' drops 'const' qualifier}}
any_cast<TestType2 &>(static_cast<any const&&>(a)); // expected-note {{requested here}}
any_cast<TestType2 &&>(static_cast<any const&&>(a)); // expected-note {{requested here}}
}

View File

@@ -0,0 +1,45 @@
//===----------------------------------------------------------------------===//
//
// 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
// <experimental/any>
// template <class ValueType>
// ValueType const any_cast(any const&);
//
// template <class ValueType>
// ValueType any_cast(any &);
//
// template <class ValueType>
// ValueType any_cast(any &&);
// Test instantiating the any_cast with a non-copyable type.
#include <experimental/any>
using std::experimental::any;
using std::experimental::any_cast;
struct no_copy
{
no_copy() {}
no_copy(no_copy &&) {}
private:
no_copy(no_copy const &);
};
int main() {
any a;
any_cast<no_copy>(static_cast<any&>(a));
any_cast<no_copy>(static_cast<any const&>(a));
any_cast<no_copy>(static_cast<any &&>(a));
// expected-error@experimental/any:* 3 {{static_assert failed "_ValueType is required to be a reference or a CopyConstructible type."}}
// expected-error@experimental/any:* 3 {{calling a private constructor of class 'no_copy'}}
}

View File

@@ -0,0 +1,37 @@
//===----------------------------------------------------------------------===//
//
// 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
// <experimental/any>
// template <class ValueType>
// ValueType const* any_cast(any const *) noexcept;
//
// template <class ValueType>
// ValueType * any_cast(any *) noexcept;
#include <experimental/any>
using std::experimental::any;
using std::experimental::any_cast;
int main()
{
any a(1);
any_cast<int &>(&a); // expected-error@experimental/any:* 1 {{static_assert failed "_ValueType may not be a reference."}}
any_cast<int &&>(&a); // expected-error@experimental/any:* 1 {{static_assert failed "_ValueType may not be a reference."}}
any_cast<int const &>(&a); // expected-error@experimental/any:* 1 {{static_assert failed "_ValueType may not be a reference."}}
any_cast<int const&&>(&a); // expected-error@experimental/any:* 1 {{static_assert failed "_ValueType may not be a reference."}}
any const& a2 = a;
any_cast<int &>(&a2); // expected-error@experimental/any:* 1 {{static_assert failed "_ValueType may not be a reference."}}
any_cast<int &&>(&a2); // expected-error@experimental/any:* 1 {{static_assert failed "_ValueType may not be a reference."}}
any_cast<int const &>(&a2); // expected-error@experimental/any:* 1 {{static_assert failed "_ValueType may not be a reference."}}
any_cast<int const &&>(&a2); // expected-error@experimental/any:* 1 {{static_assert failed "_ValueType may not be a reference."}}
}

View File

@@ -0,0 +1,40 @@
//===----------------------------------------------------------------------===//
//
// 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
// <experimental/any>
// void swap(any &, any &) noexcept
// swap(...) just wraps any::swap(...). That function is tested elsewhere.
#include <experimental/any>
#include <cassert>
using std::experimental::any;
using std::experimental::any_cast;
int main()
{
{ // test noexcept
any a;
static_assert(noexcept(swap(a, a)), "swap(any&, any&) must be noexcept");
}
{
any a1(1);
any a2(2);
swap(a1, a2);
assert(any_cast<int>(a1) == 2);
assert(any_cast<int>(a2) == 1);
}
}