// { dg-options "-std=gnu++20" }
// { dg-do run { target c++20 } }

#include <format>
#include <string>
#include <iterator>
#include <testsuite_hooks.h>

template<typename C>
struct move_only_iterator
{
  using iterator = std::back_insert_iterator<std::basic_string<C>>;
  using value_type = iterator::value_type;
  using difference_type = iterator::difference_type;
  using iterator_category = std::output_iterator_tag;

  move_only_iterator(iterator b) : base_(b) { }
  move_only_iterator(move_only_iterator&&) = default;
  move_only_iterator& operator=(move_only_iterator&&) = default;

  move_only_iterator& operator++() { ++base_; return *this; }
  move_only_iterator operator++(int) { auto tmp = *this; ++base_; return tmp; }

  decltype(auto) operator*() { return *base_; }

private:
  iterator base_;
};

void
test_move_only()
{
  const char arg1[] = "matte";
  int arg2 = '!';

  std::string str;
  move_only_iterator<char> mo(std::back_inserter(str));
  auto res = std::vformat_to(std::move(mo), "for{:.3} that{:c}",
			     std::make_format_args(arg1, arg2));
  static_assert(std::is_same_v<decltype(res), decltype(mo)>);
  VERIFY( str == "format that!" );

  const wchar_t warg1[] = L"matte";
  long warg2 = L'!';
  std::wstring wstr;
  move_only_iterator<wchar_t> wmo(std::back_inserter(wstr));
  auto wres = std::vformat_to(std::move(wmo), L"for{:.3} that{:c}",
			      std::make_wformat_args(warg1, warg2));
  static_assert(std::is_same_v<decltype(wres), decltype(wmo)>);
  VERIFY( wstr == L"format that!" );
}

int main()
{
  test_move_only();
}
