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 // <string> 11 12 // basic_string& operator=(basic_string&& c) 13 // noexcept( 14 // allocator_traits<allocator_type>::propagate_on_container_move_assignment::value || 15 // allocator_traits<allocator_type>::is_always_equal::value); // C++17 16 // 17 // before C++17, we use the conforming extension 18 // noexcept( 19 // allocator_type::propagate_on_container_move_assignment::value && 20 // is_nothrow_move_assignable<allocator_type>::value); 21 22 #include <string> 23 #include <cassert> 24 25 #include "test_macros.h" 26 #include "test_allocator.h" 27 28 template <class T> 29 struct some_alloc 30 { 31 typedef T value_type; 32 some_alloc(const some_alloc&); 33 }; 34 35 template <class T> 36 struct some_alloc2 37 { 38 typedef T value_type; 39 40 some_alloc2() {} 41 some_alloc2(const some_alloc2&); 42 void deallocate(void*, unsigned) {} 43 44 typedef std::false_type propagate_on_container_move_assignment; 45 typedef std::true_type is_always_equal; 46 }; 47 48 template <class T> 49 struct some_alloc3 50 { 51 typedef T value_type; 52 53 some_alloc3() {} 54 some_alloc3(const some_alloc3&); 55 void deallocate(void*, unsigned) {} 56 57 typedef std::false_type propagate_on_container_move_assignment; 58 typedef std::false_type is_always_equal; 59 }; 60 61 int main() 62 { 63 #if __has_feature(cxx_noexcept) 64 { 65 typedef std::string C; 66 static_assert(std::is_nothrow_move_assignable<C>::value, ""); 67 } 68 { 69 typedef std::basic_string<char, std::char_traits<char>, test_allocator<char>> C; 70 static_assert(!std::is_nothrow_move_assignable<C>::value, ""); 71 } 72 { 73 typedef std::basic_string<char, std::char_traits<char>, some_alloc<char>> C; 74 #if TEST_STD_VER > 14 75 // if the allocators are always equal, then the move assignment can be noexcept 76 static_assert( std::is_nothrow_move_assignable<C>::value, ""); 77 #else 78 static_assert(!std::is_nothrow_move_assignable<C>::value, ""); 79 #endif 80 } 81 #if TEST_STD_VER > 14 82 { 83 // POCMA is false, always equal 84 typedef std::basic_string<char, std::char_traits<char>, some_alloc2<char>> C; 85 static_assert( std::is_nothrow_move_assignable<C>::value, ""); 86 } 87 { 88 // POCMA is false, not always equal 89 typedef std::basic_string<char, std::char_traits<char>, some_alloc3<char>> C; 90 static_assert(!std::is_nothrow_move_assignable<C>::value, ""); 91 } 92 #endif 93 94 #endif 95 } 96