diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -388,7 +388,7 @@ --------------------------------------------------- ----------------- ``__cpp_lib_bind_front`` ``202306L`` --------------------------------------------------- ----------------- - ``__cpp_lib_bitset`` *unimplemented* + ``__cpp_lib_bitset`` ``202306L`` --------------------------------------------------- ----------------- ``__cpp_lib_copyable_function`` *unimplemented* --------------------------------------------------- ----------------- diff --git a/libcxx/docs/ReleaseNotes/18.rst b/libcxx/docs/ReleaseNotes/18.rst --- a/libcxx/docs/ReleaseNotes/18.rst +++ b/libcxx/docs/ReleaseNotes/18.rst @@ -38,7 +38,9 @@ Implemented Papers ------------------ + - P2497R0 - Testing for success or failure of ```` functions +- P2697R1 - Interfacing ``bitset`` with ``string_view`` Improvements and New Features diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv --- a/libcxx/docs/Status/Cxx2cPapers.csv +++ b/libcxx/docs/Status/Cxx2cPapers.csv @@ -20,7 +20,7 @@ "`P2637R3 `__","LWG","Member ``visit``","Varna June 2023","","","|format|" "`P2641R4 `__","CWG, LWG","Checking if a ``union`` alternative is active","Varna June 2023","","","" "`P1759R6 `__","LWG","Native handles and file streams","Varna June 2023","","","" -"`P2697R1 `__","LWG","Interfacing ``bitset`` with ``string_view``","Varna June 2023","","","" +"`P2697R1 `__","LWG","Interfacing ``bitset`` with ``string_view``","Varna June 2023","|Complete|","18.0","" "`P1383R2 `__","LWG","More ``constexpr`` for ```` and ````","Varna June 2023","","","" "`P2734R0 `__","LWG","Adding the new SI prefixes","Varna June 2023","|Complete|","17.0","" "`P2548R6 `__","LWG","``copyable_function``","Varna June 2023","","","" diff --git a/libcxx/include/bitset b/libcxx/include/bitset --- a/libcxx/include/bitset +++ b/libcxx/include/bitset @@ -40,15 +40,25 @@ constexpr bitset() noexcept; constexpr bitset(unsigned long long val) noexcept; template - explicit bitset(const charT* str, - typename basic_string::size_type n = basic_string::npos, - charT zero = charT('0'), charT one = charT('1')); // constexpr since C++23 + constexpr explicit bitset(const charT* str, + typename basic_string::size_type n = basic_string::npos, + charT zero = charT('0'), charT one = charT('1')); // until C++26, constexpr since C++23 + template + constexpr explicit bitset(const charT* str, + typename basic_string_view::size_type n = basic_string_view::npos, + charT zero = charT('0'), charT one = charT('1')); // since C++26 + template + explicit bitset( + const basic_string_view& str, + typename basic_string_view::size_type pos = 0, + typename basic_string_view::size_type n = basic_string_view::npos, + charT zero = charT('0'), charT one = charT('1')); // since C++26 template - explicit bitset(const basic_string& str, - typename basic_string::size_type pos = 0, - typename basic_string::size_type n = - basic_string::npos, - charT zero = charT('0'), charT one = charT('1')); // constexpr since C++23 + constexpr explicit bitset( + const basic_string& str, + typename basic_string::size_type pos = 0, + typename basic_string::size_type n = basic_string::npos, + charT zero = charT('0'), charT one = charT('1')); // constexpr since C++23 // 23.3.5.2 bitset operations: bitset& operator&=(const bitset& rhs) noexcept; // constexpr since C++23 @@ -696,13 +706,32 @@ template ::value> > _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit bitset( const _CharT* __str, +# if _LIBCPP_STD_VER >= 26 + typename basic_string_view<_CharT>::size_type __n = basic_string_view<_CharT>::npos, +# else typename basic_string<_CharT>::size_type __n = basic_string<_CharT>::npos, - _CharT __zero = _CharT('0'), - _CharT __one = _CharT('1')) { +# endif + _CharT __zero = _CharT('0'), + _CharT __one = _CharT('1')) { size_t __rlen = std::min(__n, char_traits<_CharT>::length(__str)); __init_from_string_view(basic_string_view<_CharT>(__str, __rlen), __zero, __one); } +#if _LIBCPP_STD_VER >= 26 + template + _LIBCPP_HIDE_FROM_ABI constexpr explicit bitset( + basic_string_view<_CharT, _Traits> __str, + typename basic_string_view<_CharT, _Traits>::size_type __pos = 0, + typename basic_string_view<_CharT, _Traits>::size_type __n = basic_string_view<_CharT, _Traits>::npos, + _CharT __zero = _CharT('0'), + _CharT __one = _CharT('1')) { + if (__pos > __str.size()) + __throw_out_of_range("bitset string pos out of range"); + + size_t __rlen = std::min(__n, __str.size() - __pos); + __init_from_string_view(basic_string_view<_CharT, _Traits>(__str.data() + __pos, __rlen), __zero, __one); + } +#endif template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit bitset( const basic_string<_CharT, _Traits, _Allocator>& __str, diff --git a/libcxx/include/version b/libcxx/include/version --- a/libcxx/include/version +++ b/libcxx/include/version @@ -460,7 +460,7 @@ // # define __cpp_lib_bind_back 202306L # undef __cpp_lib_bind_front # define __cpp_lib_bind_front 202306L -// # define __cpp_lib_bitset 202306L +# define __cpp_lib_bitset 202306L // # define __cpp_lib_copyable_function 202306L // # define __cpp_lib_fstream_native_handle 202306L // # define __cpp_lib_function_ref 202306L diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/bitset.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/bitset.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/bitset.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/bitset.version.compile.pass.cpp @@ -78,17 +78,11 @@ #elif TEST_STD_VER > 23 -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_bitset -# error "__cpp_lib_bitset should be defined in c++26" -# endif -# if __cpp_lib_bitset != 202306L -# error "__cpp_lib_bitset should have the value 202306L in c++26" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_bitset -# error "__cpp_lib_bitset should not be defined because it is unimplemented in libc++!" -# endif +# ifndef __cpp_lib_bitset +# error "__cpp_lib_bitset should be defined in c++26" +# endif +# if __cpp_lib_bitset != 202306L +# error "__cpp_lib_bitset should have the value 202306L in c++26" # endif # ifndef __cpp_lib_constexpr_bitset diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp @@ -5689,17 +5689,11 @@ # error "__cpp_lib_bitops should have the value 201907L in c++26" # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_bitset -# error "__cpp_lib_bitset should be defined in c++26" -# endif -# if __cpp_lib_bitset != 202306L -# error "__cpp_lib_bitset should have the value 202306L in c++26" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_bitset -# error "__cpp_lib_bitset should not be defined because it is unimplemented in libc++!" -# endif +# ifndef __cpp_lib_bitset +# error "__cpp_lib_bitset should be defined in c++26" +# endif +# if __cpp_lib_bitset != 202306L +# error "__cpp_lib_bitset should have the value 202306L in c++26" # endif # ifndef __cpp_lib_bool_constant diff --git a/libcxx/test/std/utilities/template.bitset/bitset.cons/char_ptr_ctor.pass.cpp b/libcxx/test/std/utilities/template.bitset/bitset.cons/char_ptr_ctor.pass.cpp --- a/libcxx/test/std/utilities/template.bitset/bitset.cons/char_ptr_ctor.pass.cpp +++ b/libcxx/test/std/utilities/template.bitset/bitset.cons/char_ptr_ctor.pass.cpp @@ -8,7 +8,7 @@ // template // explicit bitset(const charT* str, -// typename basic_string::size_type n = basic_string::npos, +// typename basic_string_view::size_type n = basic_string_view::npos, // s/string/string_view since C++26 // charT zero = charT('0'), charT one = charT('1')); // constexpr since C++23 #include @@ -33,12 +33,41 @@ } #endif + static_assert(!std::is_convertible >::value, ""); + static_assert(std::is_constructible, const char*>::value, ""); { - const char str[] = "1010101010"; - std::bitset v(str); + const char s[] = "1010101010"; + std::bitset v(s); std::size_t M = std::min(v.size(), 10); for (std::size_t i = 0; i < M; ++i) - assert(v[i] == (str[M - 1 - i] == '1')); + assert(v[i] == (s[M - 1 - i] == '1')); + for (std::size_t i = 10; i < v.size(); ++i) + assert(v[i] == false); + } + { + const char s[] = "1010101010"; + std::bitset v(s, 10); + std::size_t M = std::min(v.size(), 10); + for (std::size_t i = 0; i < M; ++i) + assert(v[i] == (s[M - 1 - i] == '1')); + for (std::size_t i = 10; i < v.size(); ++i) + assert(v[i] == false); + } + { + const char s[] = "1a1a1a1a1a"; + std::bitset v(s, 10, 'a'); + std::size_t M = std::min(v.size(), 10); + for (std::size_t i = 0; i < M; ++i) + assert(v[i] == (s[M - 1 - i] == '1')); + for (std::size_t i = 10; i < v.size(); ++i) + assert(v[i] == false); + } + { + const char s[] = "bababababa"; + std::bitset v(s, 10, 'a', 'b'); + std::size_t M = std::min(v.size(), 10); + for (std::size_t i = 0; i < M; ++i) + assert(v[i] == (s[M - 1 - i] == 'b')); for (std::size_t i = 10; i < v.size(); ++i) assert(v[i] == false); } diff --git a/libcxx/test/std/utilities/template.bitset/bitset.cons/string_ctor.pass.cpp b/libcxx/test/std/utilities/template.bitset/bitset.cons/string_ctor.pass.cpp --- a/libcxx/test/std/utilities/template.bitset/bitset.cons/string_ctor.pass.cpp +++ b/libcxx/test/std/utilities/template.bitset/bitset.cons/string_ctor.pass.cpp @@ -21,6 +21,14 @@ TEST_CONSTEXPR_CXX23 void test_string_ctor() { #ifndef TEST_HAS_NO_EXCEPTIONS if (!TEST_IS_CONSTANT_EVALUATED) { + try { + std::string s("xxx1010101010xxxx"); + std::bitset v(s, s.size()+1); + assert(false); + } + catch (std::out_of_range&) + { + } try { std::string s("xxx1010101010xxxx"); std::bitset v(s, s.size()+1, 10); @@ -29,6 +37,22 @@ catch (std::out_of_range&) { } + try { + std::string s("xxx1010101010xxxx"); + std::bitset v(s); + assert(false); + } + catch (std::invalid_argument&) + { + } + try { + std::string s("xxx1010101010xxxx"); + std::bitset v(s, 2); + assert(false); + } + catch (std::invalid_argument&) + { + } try { std::string s("xxx1010101010xxxx"); std::bitset v(s, 2, 10); @@ -47,6 +71,27 @@ } } #endif // TEST_HAS_NO_EXCEPTIONS + + static_assert(!std::is_convertible >::value, ""); + static_assert(std::is_constructible, std::string>::value, ""); + { + std::string s("1010101010"); + std::bitset v(s); + std::size_t M = std::min(v.size(), 10); + for (std::size_t i = 0; i < M; ++i) + assert(v[i] == (s[M - 1 - i] == '1')); + for (std::size_t i = 10; i < v.size(); ++i) + assert(v[i] == false); + } + { + std::string s("xxx1010101010"); + std::bitset v(s, 3); + std::size_t M = std::min(v.size(), 10); + for (std::size_t i = 0; i < M; ++i) + assert(v[i] == (s[3 + M - 1 - i] == '1')); + for (std::size_t i = 10; i < v.size(); ++i) + assert(v[i] == false); + } { std::string s("xxx1010101010xxxx"); std::bitset v(s, 3, 10); @@ -56,6 +101,15 @@ for (std::size_t i = 10; i < v.size(); ++i) assert(v[i] == false); } + { + std::string s("xxx1a1a1a1a1axxxx"); + std::bitset v(s, 3, 10, 'a'); + std::size_t M = std::min(v.size(), 10); + for (std::size_t i = 0; i < M; ++i) + assert(v[i] == (s[3 + M - 1 - i] == '1')); + for (std::size_t i = 10; i < v.size(); ++i) + assert(v[i] == false); + } { std::string s("xxxbababababaxxxx"); std::bitset v(s, 3, 10, 'a', 'b'); diff --git a/libcxx/test/std/utilities/template.bitset/bitset.cons/string_view_ctor.pass.cpp b/libcxx/test/std/utilities/template.bitset/bitset.cons/string_view_ctor.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/template.bitset/bitset.cons/string_view_ctor.pass.cpp @@ -0,0 +1,151 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23 + +// template +// explicit bitset( +// const basic_string_view& str, +// typename basic_string_view::size_type pos = 0, +// typename basic_string_view::size_type n = basic_string_view::npos, +// charT zero = charT('0'), charT one = charT('1')); + +#include // for 'min' and 'max' +#include +#include +#include // for 'invalid_argument' +#include +#include + +#include "test_macros.h" + +template +constexpr void test_string_ctor() { +#ifndef TEST_HAS_NO_EXCEPTIONS + if (!TEST_IS_CONSTANT_EVALUATED) { + try { + std::string_view s("xxx1010101010xxxx"); + std::bitset v(s, s.size() + 1); + assert(false); + } catch (std::out_of_range&) { + } + try { + std::string_view s("xxx1010101010xxxx"); + std::bitset v(s, s.size() + 1, 10); + assert(false); + } catch (std::out_of_range&) { + } + try { + std::string_view s("xxx1010101010xxxx"); + std::bitset v(s); + assert(false); + } catch (std::invalid_argument&) { + } + try { + std::string_view s("xxx1010101010xxxx"); + std::bitset v(s, 2); + assert(false); + } catch (std::invalid_argument&) { + } + try { + std::string_view s("xxx1010101010xxxx"); + std::bitset v(s, 2, 10); + assert(false); + } catch (std::invalid_argument&) { + } + try { + std::string_view s("xxxbababababaxxxx"); + std::bitset v(s, 2, 10, 'a', 'b'); + assert(false); + } catch (std::invalid_argument&) { + } + } +#endif // TEST_HAS_NO_EXCEPTIONS + + static_assert(!std::is_convertible_v>); + static_assert(std::is_constructible_v, std::string_view>); + { + std::string_view s("1010101010"); + std::bitset v(s); + std::size_t M = std::min(v.size(), 10); + for (std::size_t i = 0; i < M; ++i) + assert(v[i] == (s[M - 1 - i] == '1')); + for (std::size_t i = 10; i < v.size(); ++i) + assert(v[i] == false); + } + { + std::string_view s("xxx1010101010"); + std::bitset v(s, 3); + std::size_t M = std::min(v.size(), 10); + for (std::size_t i = 0; i < M; ++i) + assert(v[i] == (s[3 + M - 1 - i] == '1')); + for (std::size_t i = 10; i < v.size(); ++i) + assert(v[i] == false); + } + { + std::string_view s("xxx1010101010xxxx"); + std::bitset v(s, 3, 10); + std::size_t M = std::min(v.size(), 10); + for (std::size_t i = 0; i < M; ++i) + assert(v[i] == (s[3 + M - 1 - i] == '1')); + for (std::size_t i = 10; i < v.size(); ++i) + assert(v[i] == false); + } + { + std::string_view s("xxx1a1a1a1a1axxxx"); + std::bitset v(s, 3, 10, 'a'); + std::size_t M = std::min(v.size(), 10); + for (std::size_t i = 0; i < M; ++i) + assert(v[i] == (s[3 + M - 1 - i] == '1')); + for (std::size_t i = 10; i < v.size(); ++i) + assert(v[i] == false); + } + { + std::string_view s("xxxbababababaxxxx"); + std::bitset v(s, 3, 10, 'a', 'b'); + std::size_t M = std::min(v.size(), 10); + for (std::size_t i = 0; i < M; ++i) + assert(v[i] == (s[3 + M - 1 - i] == 'b')); + for (std::size_t i = 10; i < v.size(); ++i) + assert(v[i] == false); + } +} + +struct Nonsense { + virtual ~Nonsense() {} +}; + +constexpr void test_for_non_eager_instantiation() { + // Ensure we don't accidentally instantiate `std::basic_string_view` + // since it may not be well formed and can cause an error in the + // non-immediate context. + static_assert(!std::is_constructible, Nonsense*>::value, ""); + static_assert(!std::is_constructible, Nonsense*, std::size_t, Nonsense&, Nonsense&>::value, ""); +} + +constexpr bool test() { + test_string_ctor<0>(); + test_string_ctor<1>(); + test_string_ctor<31>(); + test_string_ctor<32>(); + test_string_ctor<33>(); + test_string_ctor<63>(); + test_string_ctor<64>(); + test_string_ctor<65>(); + test_string_ctor<1000>(); + test_for_non_eager_instantiation(); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -231,7 +231,6 @@ "name": "__cpp_lib_bitset", "values": {"c++26": 202306}, # P2697R1 Interfacing bitset with string_view "headers": ["bitset"], - "unimplemented": True, }, { "name": "__cpp_lib_bool_constant",