// { dg-do compile { target c++20 } } // { dg-require-effective-target cxx11_abi } // { dg-add-options no_pch } #include #ifndef __cpp_lib_constexpr_string # error "Feature-test macro for constexpr std::string missing in " #elif __cpp_lib_constexpr_string != 201907L # error "Feature-test macro for constexpr std::string has wrong value in " #endif #include using C = char; using T = std::char_traits; template struct Alloc : std::allocator { using std::allocator::allocator; constexpr explicit Alloc(int p) : personality(p) { } template constexpr Alloc(const Alloc& a) : personality(a.personality) { } int personality = 0; constexpr Alloc select_on_container_copy_construction() const { return Alloc(-1); } constexpr bool operator==(const Alloc& a) const noexcept { return personality == a.personality; } }; constexpr bool test_default_ctor() { std::basic_string s0; VERIFY( s0.empty() ); std::basic_string s1(std::allocator{}); VERIFY( s1.empty() ); std::basic_string> s2; VERIFY( s2.empty() ); std::basic_string> s3(Alloc(3)); VERIFY( s3.empty() ); VERIFY( s3.get_allocator().personality == 3 ); return true; } static_assert( test_default_ctor() ); constexpr bool test_cstr() { const C cs[] = "This has an embedded \0 null"; const auto len = (sizeof(cs) - 1)/sizeof(C); std::basic_string s1(cs); VERIFY( s1.length() == 21 ); std::basic_string s2(cs, std::allocator{}); VERIFY( s2 == s1 ); std::basic_string s3(cs, len); VERIFY( s3.length() == len ); VERIFY( s3[len] == '\0' ); std::basic_string s4(cs, len, std::allocator{}); VERIFY( s4 == s3 ); std::basic_string> s5(cs); VERIFY( s5 == std::basic_string_view(s1) ); std::basic_string> s6(cs, Alloc(6)); VERIFY( s6 == std::basic_string_view(s1) ); VERIFY( s6.get_allocator().personality == 6 ); std::basic_string> s7(cs, len, Alloc(7)); VERIFY( s7 == std::basic_string_view(s3) ); VERIFY( s7.get_allocator().personality == 7 ); return true; } static_assert( test_cstr() ); constexpr bool test_copy() { const std::basic_string short_string = "sh"; const std::basic_string long_string = "string longer than the SSO buffer"; std::basic_string s1 = short_string; VERIFY( s1 == short_string ); std::basic_string s2(short_string, s1.get_allocator()); VERIFY( s2 == short_string ); std::basic_string s3 = long_string; VERIFY( s3 == long_string ); std::basic_string s4(long_string, s1.get_allocator()); VERIFY( s4 == long_string ); std::basic_string> a_short_string = short_string.c_str(); std::basic_string> a_long_string = long_string.c_str(); std::basic_string> s5(a_short_string); VERIFY( s5 == a_short_string ); std::basic_string> s6(a_short_string, s5.get_allocator()); VERIFY( s6 == a_short_string ); std::basic_string> s7(a_short_string, Alloc(7)); VERIFY( s7 == a_short_string ); VERIFY( s7.get_allocator().personality == 7 ); std::basic_string> s8 = a_long_string; VERIFY( s8 == a_long_string ); std::basic_string> s9(a_long_string, s5.get_allocator()); VERIFY( s9 == a_long_string ); std::basic_string> s10(a_long_string, Alloc(10)); VERIFY( s10 == a_long_string ); VERIFY( s10.get_allocator().personality == 10 ); return true; } static_assert( test_copy() ); constexpr bool test_move() { const std::basic_string short_string = "sh"; const std::basic_string long_string = "string longer than the SSO buffer"; std::basic_string s0 = short_string; std::basic_string s1 = std::move(s0); VERIFY( s1 == short_string ); std::basic_string s2(std::move(s1), std::allocator()); VERIFY( s2 == short_string ); s0 = long_string; std::basic_string s3 = std::move(s0); VERIFY( s3 == long_string ); std::basic_string s4(std::move(s3), s1.get_allocator()); VERIFY( s4 == long_string ); std::basic_string> a_short_string = short_string.c_str(); std::basic_string> a_long_string = long_string.c_str(); auto sa0 = a_short_string; std::basic_string> s5 = std::move(sa0); VERIFY( s5 == a_short_string ); std::basic_string> s6(std::move(s5), sa0.get_allocator()); VERIFY( s6 == a_short_string ); std::basic_string> s7(std::move(s6), Alloc(7)); VERIFY( s7 == a_short_string ); VERIFY( s7.get_allocator().personality == 7 ); sa0 = a_long_string; std::basic_string> s8 = std::move(sa0); VERIFY( s8 == a_long_string ); std::basic_string> s9(std::move(s8), s5.get_allocator()); VERIFY( s9 == a_long_string ); std::basic_string> s10(std::move(s9), Alloc(10)); VERIFY( s10 == a_long_string ); VERIFY( s10.get_allocator().personality == 10 ); return true; } static_assert( test_move() );