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, c++14
11
12// <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 <any>
24#include <cassert>
25
26#include "any_helpers.h"
27#include "count_new.hpp"
28#include "test_macros.h"
29
30using std::any;
31using std::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// Test that any(ValueType&&) is *never* selected for a std::in_place_type_t specialization.
110void test_sfinae_constraints() {
111    using BadTag = std::in_place_type_t<int>;
112    using OKTag = std::in_place_t;
113    // Test that the tag type is properly handled in SFINAE
114    BadTag t = std::in_place_type<int>;
115    OKTag ot = std::in_place;
116    {
117        std::any a(t);
118        assertContains<int>(a, 0);
119    }
120    {
121        std::any a(std::move(t));
122        assertContains<int>(a, 0);
123    }
124    {
125        std::any a(ot);
126        assert(containsType<OKTag>(a));
127    }
128    {
129        struct Dummy { Dummy() = delete; };
130        using T = std::in_place_type_t<Dummy>;
131        static_assert(!std::is_constructible<std::any, T>::value, "");
132    }
133    {
134        // Test that the ValueType&& constructor SFINAE's away when the
135        // argument is non-copyable
136        struct NoCopy {
137          NoCopy() = default;
138          NoCopy(NoCopy const&) = delete;
139          NoCopy(int) {}
140        };
141        static_assert(!std::is_constructible<std::any, NoCopy>::value, "");
142        static_assert(!std::is_constructible<std::any, NoCopy&>::value, "");
143        static_assert(!std::is_convertible<NoCopy, std::any>::value, "");
144    }
145}
146
147int main() {
148    test_copy_move_value<small>();
149    test_copy_move_value<large>();
150    test_copy_value_throws<small_throws_on_copy>();
151    test_copy_value_throws<large_throws_on_copy>();
152    test_move_value_throws();
153    test_sfinae_constraints();
154}