brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.7 KiB · 3d3ecf9 Raw
285 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++1410 11// <any>12 13// template <class T, class ...Args> T& emplace(Args&&...);14// template <class T, class U, class ...Args>15// T& emplace(initializer_list<U>, Args&&...);16 17#include <any>18#include <cassert>19 20#include "any_helpers.h"21#include "count_new.h"22#include "test_macros.h"23 24struct Tracked {25    static int count;26    Tracked() { ++count; }27    Tracked(Tracked const&) noexcept { ++count; }28    Tracked& operator=(Tracked const&) = default;29    ~Tracked() { --count; }30};31int Tracked::count = 0;32 33template <class Type>34void test_emplace_type() {35    // constructing from a small type should perform no allocations.36    DisableAllocationGuard g(isSmallType<Type>()); ((void)g);37    assert(Type::count == 0);38    Type::reset();39    {40        std::any a(std::in_place_type<Tracked>);41        assert(Tracked::count == 1);42 43        auto &v = a.emplace<Type>();44        static_assert( std::is_same_v<Type&, decltype(v)>, "" );45        assert(&v == std::any_cast<Type>(&a));46 47        assert(Tracked::count == 0);48        assert(Type::count == 1);49        assert(Type::copied == 0);50        assert(Type::moved == 0);51        assertContains<Type>(a, 0);52    }53    assert(Type::count == 0);54    Type::reset();55    {56        std::any a(std::in_place_type<Tracked>);57        assert(Tracked::count == 1);58 59        auto &v = a.emplace<Type>(101);60        static_assert( std::is_same_v<Type&, decltype(v)>, "" );61        assert(&v == std::any_cast<Type>(&a));62 63        assert(Tracked::count == 0);64        assert(Type::count == 1);65        assert(Type::copied == 0);66        assert(Type::moved == 0);67        assertContains<Type>(a, 101);68    }69    assert(Type::count == 0);70    Type::reset();71    {72        std::any a(std::in_place_type<Tracked>);73        assert(Tracked::count == 1);74 75        auto &v = a.emplace<Type>(-1, 42, -1);76        static_assert( std::is_same_v<Type&, decltype(v)>, "" );77        assert(&v == std::any_cast<Type>(&a));78 79        assert(Tracked::count == 0);80        assert(Type::count == 1);81        assert(Type::copied == 0);82        assert(Type::moved == 0);83        assertContains<Type>(a, 42);84    }85    assert(Type::count == 0);86    Type::reset();87}88 89template <class Type>90void test_emplace_type_tracked() {91    // constructing from a small type should perform no allocations.92    DisableAllocationGuard g(isSmallType<Type>()); ((void)g);93    {94        std::any a(std::in_place_type<Tracked>);95        assert(Tracked::count == 1);96        auto &v = a.emplace<Type>();97        static_assert( std::is_same_v<Type&, decltype(v)>, "" );98        assert(&v == std::any_cast<Type>(&a));99 100        assert(Tracked::count == 0);101        assertArgsMatch<Type>(a);102    }103    {104        std::any a(std::in_place_type<Tracked>);105        assert(Tracked::count == 1);106        auto &v = a.emplace<Type>(-1, 42, -1);107        static_assert( std::is_same_v<Type&, decltype(v)>, "" );108        assert(&v == std::any_cast<Type>(&a));109 110        assert(Tracked::count == 0);111        assertArgsMatch<Type, int, int, int>(a);112    }113    // initializer_list constructor tests114    {115        std::any a(std::in_place_type<Tracked>);116        assert(Tracked::count == 1);117        auto &v = a.emplace<Type>({-1, 42, -1});118        static_assert( std::is_same_v<Type&, decltype(v)>, "" );119        assert(&v == std::any_cast<Type>(&a));120 121        assert(Tracked::count == 0);122        assertArgsMatch<Type, std::initializer_list<int>>(a);123    }124    {125        int x = 42;126        std::any a(std::in_place_type<Tracked>);127        assert(Tracked::count == 1);128        auto &v = a.emplace<Type>({-1, 42, -1}, x);129        static_assert( std::is_same_v<Type&, decltype(v)>, "" );130        assert(&v == std::any_cast<Type>(&a));131 132        assert(Tracked::count == 0);133        assertArgsMatch<Type, std::initializer_list<int>, int&>(a);134    }135}136 137#ifndef TEST_HAS_NO_EXCEPTIONS138 139struct SmallThrows {140  SmallThrows(int) { throw 42; }141  SmallThrows(std::initializer_list<int>, int) { throw 42; }142};143static_assert(IsSmallObject<SmallThrows>::value, "");144 145struct LargeThrows {146  LargeThrows(int) { throw 42; }147  LargeThrows(std::initializer_list<int>, int) { throw 42; }148  int data[sizeof(std::any)];149};150static_assert(!IsSmallObject<LargeThrows>::value, "");151 152template <class Type>153void test_emplace_throws()154{155    // any stores small type156    {157        std::any a(small{42});158        assert(small::count == 1);159        try {160            auto &v = a.emplace<Type>(101);161            static_assert( std::is_same_v<Type&, decltype(v)>, "" );162            assert(false);163        } catch (int const&) {164        }165        assert(small::count == 0);166    }167    {168        std::any a(small{42});169        assert(small::count == 1);170        try {171            auto &v = a.emplace<Type>({1, 2, 3}, 101);172            static_assert( std::is_same_v<Type&, decltype(v)>, "" );173            assert(false);174        } catch (int const&) {175        }176        assert(small::count == 0);177    }178    // any stores large type179    {180        std::any a(large{42});181        assert(large::count == 1);182        try {183            auto &v = a.emplace<Type>(101);184            static_assert( std::is_same_v<Type&, decltype(v)>, "" );185            assert(false);186        } catch (int const&) {187        }188        assert(large::count == 0);189    }190    {191        std::any a(large{42});192        assert(large::count == 1);193        try {194            auto &v = a.emplace<Type>({1, 2, 3}, 101);195            static_assert( std::is_same_v<Type&, decltype(v)>, "" );196            assert(false);197        } catch (int const&) {198        }199        assert(large::count == 0);200    }201}202 203#endif204 205template <class T, class ...Args>206constexpr auto has_emplace(int)207    -> decltype(std::any{}.emplace<T>(std::declval<Args>()...), true) { return true; }208 209template <class ...Args>210constexpr bool has_emplace(long) { return false; }211 212template <class ...Args>213constexpr bool has_emplace() { return has_emplace<Args...>(0); }214 215 216template <class T, class IT, class ...Args>217constexpr auto has_emplace_init_list(int)218    -> decltype(std::any{}.emplace<T>(219        {std::declval<IT>(), std::declval<IT>(), std::declval<IT>()},220        std::declval<Args>()...), true) { return true; }221 222template <class ...Args>223constexpr bool has_emplace_init_list(long) { return false; }224 225template <class ...Args>226constexpr bool has_emplace_init_list() { return has_emplace_init_list<Args...>(0); }227 228 229void test_emplace_sfinae_constraints() {230    {231        static_assert(has_emplace<int>(), "");232        static_assert(has_emplace<int, int>(), "");233        static_assert(!has_emplace<int, int, int>(), "not constructible");234        static_assert(!has_emplace_init_list<int, int>(), "not constructible from il");235    }236    {237        static_assert(has_emplace<small>(), "");238        static_assert(has_emplace<large>(), "");239        static_assert(!has_emplace<small, void*>(), "");240        static_assert(!has_emplace<large, void*>(), "");241 242        static_assert(has_emplace_init_list<small, int>(), "");243        static_assert(has_emplace_init_list<large, int>(), "");244        static_assert(!has_emplace_init_list<small, void*>(), "");245        static_assert(!has_emplace_init_list<large, void*>(), "");246    }247    {248        // Test that the emplace SFINAE's away when the249        // argument is non-copyable250        struct NoCopy {251          NoCopy() = default;252          NoCopy(NoCopy const&) = delete;253          NoCopy(int) {}254          NoCopy(std::initializer_list<int>, int, int) {}255        };256        static_assert(!has_emplace<NoCopy>(), "");257        static_assert(!has_emplace<NoCopy, int>(), "");258        static_assert(!has_emplace_init_list<NoCopy, int, int, int>(), "");259        static_assert(!has_emplace<NoCopy&>(), "");260        static_assert(!has_emplace<NoCopy&, int>(), "");261        static_assert(!has_emplace_init_list<NoCopy&, int, int, int>(), "");262        static_assert(!has_emplace<NoCopy&&>(), "");263        static_assert(!has_emplace<NoCopy&&, int>(), "");264        static_assert(!has_emplace_init_list<NoCopy&&, int, int, int>(), "");265 266    }267}268 269int main(int, char**) {270    test_emplace_type<small>();271    test_emplace_type<large>();272    test_emplace_type<small_throws_on_copy>();273    test_emplace_type<large_throws_on_copy>();274    test_emplace_type<throws_on_move>();275    test_emplace_type_tracked<small_tracked_t>();276    test_emplace_type_tracked<large_tracked_t>();277    test_emplace_sfinae_constraints();278#ifndef TEST_HAS_NO_EXCEPTIONS279    test_emplace_throws<SmallThrows>();280    test_emplace_throws<LargeThrows>();281#endif282 283  return 0;284}285