1//===----------------------------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// UNSUPPORTED: c++98, c++03, c++11
11
12// <experimental/any>
13
14// template <class Value> any(Value &&)
15
16// Test construction from a value.
17// Concerns:
18// ---------
19// 1. The value is properly move/copied depending on the value category.
20// 2. Both small and large values are properly handled.
21
22
23#include <experimental/any>
24#include <cassert>
25
26#include "experimental_any_helpers.h"
27#include "count_new.hpp"
28#include "test_macros.h"
29
30using std::experimental::any;
31using std::experimental::any_cast;
32
33template <class Type>
34void test_copy_value_throws()
35{
36#if !defined(TEST_HAS_NO_EXCEPTIONS)
37    assert(Type::count == 0);
38    {
39        Type const t(42);
40        assert(Type::count == 1);
41        try {
42            any const a2(t);
43            assert(false);
44        } catch (my_any_exception const &) {
45            // do nothing
46        } catch (...) {
47            assert(false);
48        }
49        assert(Type::count == 1);
50        assert(t.value == 42);
51    }
52    assert(Type::count == 0);
53#endif
54}
55
56void test_move_value_throws()
57{
58#if !defined(TEST_HAS_NO_EXCEPTIONS)
59    assert(throws_on_move::count == 0);
60    {
61        throws_on_move v;
62        assert(throws_on_move::count == 1);
63        try {
64            any const a(std::move(v));
65            assert(false);
66        } catch (my_any_exception const &) {
67            // do nothing
68        } catch (...) {
69            assert(false);
70        }
71        assert(throws_on_move::count == 1);
72    }
73    assert(throws_on_move::count == 0);
74#endif
75}
76
77template <class Type>
78void test_copy_move_value() {
79    // constructing from a small type should perform no allocations.
80    DisableAllocationGuard g(isSmallType<Type>()); ((void)g);
81    assert(Type::count == 0);
82    Type::reset();
83    {
84        Type t(42);
85        assert(Type::count == 1);
86
87        any a(t);
88
89        assert(Type::count == 2);
90        assert(Type::copied == 1);
91        assert(Type::moved == 0);
92        assertContains<Type>(a, 42);
93    }
94    assert(Type::count == 0);
95    Type::reset();
96    {
97        Type t(42);
98        assert(Type::count == 1);
99
100        any a(std::move(t));
101
102        assert(Type::count == 2);
103        assert(Type::copied == 0);
104        assert(Type::moved == 1);
105        assertContains<Type>(a, 42);
106    }
107}
108
109
110int main() {
111    test_copy_move_value<small>();
112    test_copy_move_value<large>();
113    test_copy_value_throws<small_throws_on_copy>();
114    test_copy_value_throws<large_throws_on_copy>();
115    test_move_value_throws();
116}