Mark LWG3573 as complete. It involves a change in wording around when
basic_string_view's constructor for iterator/sentinel can throw. The
current implementation is not marked conditionally noexcept, so there
is nothing to do here. Add a test that binds this behavior to verify the
constructor is not marked noexcept(true) when end - begin throws.
Details
- Reviewers
ldionne • Quuxplusone Mordante - Group Reviewers
Restricted Project - Commits
- rG494dad6b72d4: [libc++][NFC] Mark LWG3573 as complete
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
Thanks for addressing these LWG-issues.
libcxx/test/std/strings/string.view/string.view.cons/from_iterator_sentinel.pass.cpp | ||
---|---|---|
54 | It's possible to use Clang in a way it won't throw exceptions. This test fails in that context. Please guard all code you added with #ifndef TEST_HAS_NO_EXCEPTIONS. | |
55 | Is there a reason for this return? | |
59 | I'm not fond of constexpr since throwing isn't allowed in a constexpr function. | |
64 | Please test the result of comparing the exception's what() against "LWG 3573". |
libcxx/test/std/strings/string.view/string.view.cons/from_iterator_sentinel.pass.cpp | ||
---|---|---|
54 | You should know I'm going to object every time someone adds a global-namespace overloaded operator to a type that already defines its own operators. If throwing_sized_sentinel<I> IS-A sized_sentinel<I>, then its operator- shouldn't be doing anything different from the existing operator- of sized_sentinel<I>. I think we can get by with template<class CharT> struct ThrowingSentinel { friend bool operator==(const CharT*, ThrowingSentinel) noexcept; friend int operator-(const CharT *, ThrowingSentinel) noexcept; friend int operator-(ThrowingSentinel, const CharT *) { throw 42; } }; template<class CharT> void test_throwing() { auto val = MAKE_STRING_VIEW(CharT, "test"); try { (void)std::basic_string_view<CharT>(val.begin(), ThrowingSentinel()); assert(false); } catch (int i) { assert(i == 42); } } ~~~ test_throwing<char>(); #ifndef TEST_HAS_NO_WIDE_CHARACTERS test_throwing<wchar_t>(); #endif test_throwing<char8_t>(); test_throwing<char16_t>(); test_throwing<char32_t>(); (I marked some undefined functions noexcept merely to try to be evil and trick the library into getting some intermediate noexcept-specification wrong. I don't really care about those noexcepts. Those functions are undefined because they will never be called.) |
libcxx/test/std/strings/string.view/string.view.cons/from_iterator_sentinel.pass.cpp | ||
---|---|---|
54 | Good call, just guarded with TEST_HAS_NO_EXCEPTIONS. | |
54 | Your suggestions are a good refactoring indeed -- just applied them. I did feel a bit bad writing that original operator- for throwing_sized_sentinel, but it did satisfy the requirements for the test. :) As for the concept for sized_sentinel_for, it does indeed *need* to return std::iter_difference_t<I>. Note that your original writing with a return type of int would hard error in concept checking sized_sentinel_for for example. I'll wave my hands a bit on whether the return *is in fact reachable* (because in this case it's not due to the unconditional throwing, but it still "works"). | |
55 | It originally was strictly required to avoid hard erroring during concept checking sized_sentinel_for. | |
59 | Removed. |
Can you try to fix the CI? Also please verify the Cxx2bIssues.csv changes are still there. Maybe you need to rebase due to recent changes I did. Other then that it looks good.
Add bodies to operator== and operator- for ThrowingSizedSentinel to avoid GCC warning about -Wnon-template-friend.
Just rebased and resolved the conflicts in Cxx2bIssues.csv. Also worked around the GCC warning causing CI to fail.
@Mordante @Quuxplusone this should be ready now!
It's possible to use Clang in a way it won't throw exceptions. This test fails in that context. Please guard all code you added with #ifndef TEST_HAS_NO_EXCEPTIONS.