diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -384,7 +384,7 @@ --------------------------------------------------- ----------------- ``__cpp_lib_bind_front`` ``202306L`` --------------------------------------------------- ----------------- - ``__cpp_lib_bitset`` *unimplemented* + ``__cpp_lib_bitset`` ``202306L`` --------------------------------------------------- ----------------- ``__cpp_lib_copyable_function`` *unimplemented* --------------------------------------------------- ----------------- 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|","Clang 17","" "`P1383R2 `__","LWG","More ``constexpr`` for ```` and ````","Varna June 2023","","","" "`P2734R0 `__","LWG","Adding the new SI prefixes","Varna June 2023","","","" "`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,22 @@ 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_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 + 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 @@ -122,6 +129,7 @@ #include #include #include +#include #include // standard-mandated includes @@ -694,8 +702,21 @@ 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, +#endif _CharT __zero = _CharT('0'), _CharT __one = _CharT('1')); +#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')); +#endif template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit bitset(const basic_string<_CharT,_Traits,_Allocator>& __str, @@ -789,7 +810,11 @@ template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bitset<_Size>::bitset(const _CharT* __str, +#if _LIBCPP_STD_VER >= 26 + typename basic_string_view<_CharT>::size_type __n, +#else typename basic_string<_CharT>::size_type __n, +#endif _CharT __zero, _CharT __one) { size_t __rlen = _VSTD::min(__n, char_traits<_CharT>::length(__str)); @@ -807,6 +832,33 @@ _VSTD::fill(base::__make_iter(__i), base::__make_iter(_Size), false); } +#if _LIBCPP_STD_VER >= 26 +template +template +_LIBCPP_HIDE_FROM_ABI constexpr bitset<_Size>::bitset( + basic_string_view<_CharT, _Traits> __str, + typename basic_string_view<_CharT, _Traits>::size_type __pos, + typename basic_string_view<_CharT, _Traits>::size_type __n, + _CharT __zero, + _CharT __one) { + if (__pos > __str.size()) + __throw_out_of_range("bitset string pos out of range"); + + size_t __rlen = std::min(__n, __str.size() - __pos); + for (size_t __i = __pos; __i < __pos + __rlen; ++__i) + if (!_Traits::eq(__str[__i], __zero) && !_Traits::eq(__str[__i], __one)) + __throw_invalid_argument("bitset string ctor has invalid argument"); + + size_t __mp = std::min(__rlen, _Size); + size_t __i = 0; + for (; __i < __mp; ++__i) { + _CharT __c = __str[__pos + __mp - 1 - __i]; + (*this)[__i] = _Traits::eq(__c, __one); + } + std::fill(base::__make_iter(__i), base::__make_iter(_Size), false); +} +#endif // _LIBCPP_STD_VER >= 26 + template template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 diff --git a/libcxx/include/version b/libcxx/include/version --- a/libcxx/include/version +++ b/libcxx/include/version @@ -451,7 +451,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 202606L 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 @@ -5628,17 +5628,11 @@ # endif # 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 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,103 @@ +//===----------------------------------------------------------------------===// +// +// 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, 10); + assert(false); + } catch (std::out_of_range&) { + } + 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 + { + 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("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 @@ -232,7 +232,6 @@ "name": "__cpp_lib_bitset", "values": {"c++26": 202306}, # P2697R1 Interfacing bitset with string_view "headers": ["bitset"], - "unimplemented": True, }, { "name": "__cpp_lib_bool_constant",