103 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++14, c++17, c++2010 11// <flat_map>12 13// flat_map(flat_map&&)14// noexcept(is_nothrow_move_constructible<key_container_type>::value &&15// is_nothrow_move_constructible<mapped_container_type>::value &&16// is_nothrow_copy_constructible<key_compare>::value);17 18// This tests a conforming extension19 20#include <cassert>21#include <deque>22#include <flat_map>23#include <functional>24#include <memory>25#include <type_traits>26#include <vector>27 28#include "test_macros.h"29#include "MoveOnly.h"30#include "test_allocator.h"31 32template <class T>33struct ThrowingMoveAllocator {34 using value_type = T;35 explicit ThrowingMoveAllocator() = default;36 ThrowingMoveAllocator(const ThrowingMoveAllocator&) = default;37 ThrowingMoveAllocator(ThrowingMoveAllocator&&) noexcept(false) {}38 T* allocate(std::ptrdiff_t n) { return std::allocator<T>().allocate(n); }39 void deallocate(T* p, std::ptrdiff_t n) { return std::allocator<T>().deallocate(p, n); }40 friend bool operator==(ThrowingMoveAllocator, ThrowingMoveAllocator) = default;41};42 43struct ThrowingMoveComp {44 ThrowingMoveComp() = default;45 ThrowingMoveComp(const ThrowingMoveComp&) noexcept(true) {}46 ThrowingMoveComp(ThrowingMoveComp&&) noexcept(false) {}47 bool operator()(const auto&, const auto&) const { return false; }48};49 50struct MoveSensitiveComp {51 MoveSensitiveComp() noexcept(false) = default;52 MoveSensitiveComp(const MoveSensitiveComp&) noexcept = default;53 MoveSensitiveComp(MoveSensitiveComp&& rhs) { rhs.is_moved_from_ = true; }54 MoveSensitiveComp& operator=(const MoveSensitiveComp&) noexcept(false) = default;55 MoveSensitiveComp& operator=(MoveSensitiveComp&& rhs) {56 rhs.is_moved_from_ = true;57 return *this;58 }59 bool operator()(const auto&, const auto&) const { return false; }60 bool is_moved_from_ = false;61};62 63int main(int, char**) {64 {65 using C = std::flat_map<int, int>;66 LIBCPP_STATIC_ASSERT(std::is_nothrow_move_constructible_v<C>);67 C c;68 C d = std::move(c);69 }70 {71 using C = std::flat_map<int, int, std::less<int>, std::deque<int, test_allocator<int>>>;72 LIBCPP_STATIC_ASSERT(std::is_nothrow_move_constructible_v<C>);73 C c;74 C d = std::move(c);75 }76#if _LIBCPP_VERSION77 {78 // Container fails to be nothrow-move-constructible; this relies on libc++'s support for non-nothrow-copyable allocators79 using C = std::flat_map<int, int, std::less<int>, std::deque<int, ThrowingMoveAllocator<int>>, std::vector<int>>;80 static_assert(!std::is_nothrow_move_constructible_v<std::deque<int, ThrowingMoveAllocator<int>>>);81 static_assert(!std::is_nothrow_move_constructible_v<C>);82 C c;83 C d = std::move(c);84 }85 {86 // Container fails to be nothrow-move-constructible; this relies on libc++'s support for non-nothrow-copyable allocators87 using C = std::flat_map<int, int, std::less<int>, std::vector<int>, std::deque<int, ThrowingMoveAllocator<int>>>;88 static_assert(!std::is_nothrow_move_constructible_v<std::deque<int, ThrowingMoveAllocator<int>>>);89 static_assert(!std::is_nothrow_move_constructible_v<C>);90 C c;91 C d = std::move(c);92 }93#endif // _LIBCPP_VERSION94 {95 // Comparator fails to be nothrow-move-constructible96 using C = std::flat_map<int, int, ThrowingMoveComp>;97 static_assert(!std::is_nothrow_move_constructible_v<C>);98 C c;99 C d = std::move(c);100 }101 return 0;102}103