Skip to content

[libc++] Implements LWG3600 Making istream_iterator copy constructor trivial is an ABI break #127343

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx23Issues.csv
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@
"`LWG3569 <https://wg21.link/LWG3569>`__","``join_view`` fails to support ranges of ranges with non-default_initializable iterators","2022-11 (Kona)","","",""
"`LWG3594 <https://wg21.link/LWG3594>`__","``inout_ptr`` — inconsistent ``release()`` in destructor","2022-11 (Kona)","|Complete|","19",""
"`LWG3597 <https://wg21.link/LWG3597>`__","Unsigned integer types don't model advanceable","2022-11 (Kona)","","",""
"`LWG3600 <https://wg21.link/LWG3600>`__","Making ``istream_iterator`` copy constructor trivial is an ABI break","2022-11 (Kona)","","",""
"`LWG3600 <https://wg21.link/LWG3600>`__","Making ``istream_iterator`` copy constructor trivial is an ABI break","2022-11 (Kona)","|Nothing To Do|","",""
"`LWG3629 <https://wg21.link/LWG3629>`__","``make_error_code`` and ``make_error_condition`` are customization points","2022-11 (Kona)","|Complete|","16",""
"`LWG3636 <https://wg21.link/LWG3636>`__","``formatter<T>::format`` should be ``const``-qualified","2022-11 (Kona)","|Complete|","16",""
"`LWG3646 <https://wg21.link/LWG3646>`__","``std::ranges::view_interface::size`` returns a signed type","2022-11 (Kona)","|Complete|","16",""
Expand Down
3 changes: 3 additions & 0 deletions libcxx/include/__iterator/istream_iterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ class _LIBCPP_TEMPLATE_VIS istream_iterator
__in_stream_ = nullptr;
}

// LWG3600 Changed the wording of the copy constructor. In libc++ this constructor
// can still be trivial after this change.

Comment on lines +61 to +63
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd much rather just mention that our copy construct or trivial as a conforming extension. I don't think it's useful in the future to know which LWG issue changed that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the LWG issue number to let the reader know we did look at this constructor for LWG3600.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what you're trying to say with "we did look at this constructor for LWG3600". Do you mean we checked whether we're conforming because LWG3600 exists? If you mean that, I'm really not sure why anybody would care.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I care a lot. In the past we had several LWG issues closed as Completed or Nothing To Do when that was not correct. By explicitly mentioning it, it will safe time when somebody notices a difference between libc++ and the Standard.

_LIBCPP_HIDE_FROM_ABI const _Tp& operator*() const { return __value_; }
_LIBCPP_HIDE_FROM_ABI const _Tp* operator->() const { return std::addressof((operator*())); }
_LIBCPP_HIDE_FROM_ABI istream_iterator& operator++() {
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/iterator
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ public:
istream_iterator(); // constexpr since C++11
constexpr istream_iterator(default_sentinel_t); // since C++20
istream_iterator(istream_type& s);
istream_iterator(const istream_iterator& x);
constexpr istream_iterator(const istream_iterator& x) noexcept(see below);
~istream_iterator();

const T& operator*() const;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,45 @@

// class istream_iterator

// istream_iterator(const istream_iterator& x);
// C++17 says: If is_trivially_copy_constructible_v<T> is true, then
// this constructor is a trivial copy constructor.
// istream_iterator(const istream_iterator& x) noexcept(see below);

#include <iterator>
#include <sstream>
#include <cassert>

#include "test_macros.h"

// The copy constructor is constexpr in C++11, but that is not easy to test.
// The comparison of the class is not constexpr so this is only a compile test.
TEST_CONSTEXPR_CXX14 bool test_constexpr() {
std::istream_iterator<int> io;
[[maybe_unused]] std::istream_iterator<int> i = io;

return true;
}

struct thowing_copy_constructor {
thowing_copy_constructor() {}
thowing_copy_constructor(const thowing_copy_constructor&) TEST_NOEXCEPT_FALSE {}
};

int main(int, char**)
{
{
std::istream_iterator<int> io;
std::istream_iterator<int> i = io;
assert(i == std::istream_iterator<int>());
#if TEST_STD_VER >= 11
static_assert(std::is_nothrow_copy_constructible<std::istream_iterator<int>>::value, "");
#endif
}
{
std::istream_iterator<thowing_copy_constructor> io;
std::istream_iterator<thowing_copy_constructor> i = io;
assert(i == std::istream_iterator<thowing_copy_constructor>());
#if TEST_STD_VER >= 11
static_assert(!std::is_nothrow_copy_constructible<std::istream_iterator<thowing_copy_constructor>>::value, "");
#endif
}
{
std::istringstream inf(" 1 23");
Expand All @@ -37,5 +60,9 @@ int main(int, char**)
assert(j == 1);
}

return 0;
#if TEST_STD_VER >= 14
static_assert(test_constexpr(), "");
#endif

return 0;
}
Loading