(root)/
gcc-13.2.0/
libstdc++-v3/
testsuite/
24_iterators/
common_iterator/
100823.cc
// { dg-options "-std=gnu++20 -D_GLIBCXX_ASSERTIONS" }
// { dg-do run { target c++20 } }
#include <iterator>
#include <testsuite_iterators.h>
#include <testsuite_hooks.h>

void
test_triviality()
{
  using I = std::common_iterator<int*, const int*>;

  // Cannot be trivial, because it has to initialize members.
  static_assert( ! std::is_trivially_default_constructible_v<I> );

  static_assert( std::is_trivially_destructible_v<I> );
  static_assert( std::is_trivially_copy_constructible_v<I> );
  static_assert( std::is_trivially_copy_assignable_v<I> );
  static_assert( std::is_trivially_move_constructible_v<I> );
  static_assert( std::is_trivially_move_assignable_v<I> );
}

void
test_valueless_assignment()
{
  int x[1] { };
  __gnu_test::test_forward_range<int> r(x);
  using Iter = decltype(r.begin());
  using Sent = decltype(r.end());

  std::common_iterator<Iter, Sent> i;
  const std::common_iterator<Iter, Sent> j(r.begin());
  try
  {
    struct Bomb
    {
      bool operator==(Iter) const { return true; }
      operator Sent() const { throw 1; }
    };
    std::common_iterator<Iter, Bomb> b{Bomb{}};
    i = b; // Throws, leaving i valueless-by-exception.
    VERIFY(false);
  }
  catch (int)
  {
    std::common_iterator<Iter, Sent> k(i);

    // PR libstdc++/100823
    k = i; // Valid even though both operands are valueless.

    i = j; // No longer valueless.
  }
  VERIFY( i == j );
}

int main()
{
  test_valueless_assignment();
}