Hello!

The attached patch implements adds support for P2591R5 in libstdc++ (concatenation of strings and string_views, approved in Tokyo for C++26).

Thank you,
--
Giuseppe D'Angelo
From 0a4d44196bced41d97d8086343786b52a6f75faf Mon Sep 17 00:00:00 2001
From: Giuseppe D'Angelo <giuseppe.dang...@kdab.com>
Date: Tue, 30 Jul 2024 08:57:13 +0200
Subject: [PATCH] libstdc++: implement concatenation of strings and
 string_views

This adds support for P2591R5, merged for C++26.

libstdc++-v3/ChangeLog:

	* include/bits/basic_string.h: Implement the four operator+
	overloads between basic_string and (types convertible to)
	basic_string_view.
	* include/bits/version.def: Bump the feature-testing macro.
	* include/bits/version.h: Regenerate.
	* testsuite/21_strings/basic_string/operators/char/op_plus_fspath_cpp17_fail.cc: New test.
	* testsuite/21_strings/basic_string/operators/char/op_plus_fspath_cpp2c_fail.cc: New test.
	* testsuite/21_strings/basic_string/operators/char/op_plus_fspath_impl.h: New test.
	* testsuite/21_strings/basic_string/operators/char/op_plus_string_view.cc: New test.
	* testsuite/21_strings/basic_string/operators/char/op_plus_string_view_compat_fail.cc:
	New test.
	* testsuite/21_strings/basic_string/operators/char/op_plus_string_view_compat_impl.h:
	New test.
	* testsuite/21_strings/basic_string/operators/char/op_plus_string_view_compat_ok.cc:
	New test.
---
 libstdc++-v3/include/bits/basic_string.h      |  48 +++++
 libstdc++-v3/include/bits/version.def         |   5 +
 libstdc++-v3/include/bits/version.h           |   7 +-
 .../char/op_plus_fspath_cpp17_fail.cc         |  21 ++
 .../char/op_plus_fspath_cpp2c_fail.cc         |  22 +++
 .../operators/char/op_plus_fspath_impl.h      |  26 +++
 .../operators/char/op_plus_string_view.cc     | 187 ++++++++++++++++++
 .../char/op_plus_string_view_compat_fail.cc   |  22 +++
 .../char/op_plus_string_view_compat_impl.h    |  75 +++++++
 .../char/op_plus_string_view_compat_ok.cc     |  20 ++
 10 files changed, 432 insertions(+), 1 deletion(-)
 create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_fspath_cpp17_fail.cc
 create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_fspath_cpp2c_fail.cc
 create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_fspath_impl.h
 create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_string_view.cc
 create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_string_view_compat_fail.cc
 create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_string_view_compat_impl.h
 create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_string_view_compat_ok.cc

diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index 8a695a494ef..bf9ad2be00a 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -3742,6 +3742,54 @@ _GLIBCXX_END_NAMESPACE_CXX11
     { return std::move(__lhs.append(1, __rhs)); }
 #endif
 
+#if __cplusplus > 202302L
+  // const string & + string_view
+  template<typename _CharT, typename _Traits, typename _Alloc>
+    _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
+    inline basic_string<_CharT, _Traits, _Alloc>
+    operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
+	       __type_identity_t<basic_string_view<_CharT, _Traits>> __rhs)
+    {
+      typedef basic_string<_CharT, _Traits, _Alloc> _Str;
+      return std::__str_concat<_Str>(__lhs.data(), __lhs.size(),
+				      __rhs.data(), __rhs.size(),
+				      __lhs.get_allocator());
+    }
+
+  // string && + string_view
+  template<typename _CharT, typename _Traits, typename _Alloc>
+    _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
+    inline basic_string<_CharT, _Traits, _Alloc>
+    operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
+	       __type_identity_t<basic_string_view<_CharT, _Traits>> __rhs)
+    {
+      return std::move(__lhs.append(__rhs));
+    }
+
+  // string_view + const string &
+  template<typename _CharT, typename _Traits, typename _Alloc>
+    _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
+    inline basic_string<_CharT, _Traits, _Alloc>
+    operator+(__type_identity_t<basic_string_view<_CharT, _Traits>> __lhs,
+	       const basic_string<_CharT, _Traits, _Alloc>& __rhs)
+    {
+      typedef basic_string<_CharT, _Traits, _Alloc> _Str;
+      return std::__str_concat<_Str>(__lhs.data(), __lhs.size(),
+				      __rhs.data(), __rhs.size(),
+				      __rhs.get_allocator());
+    }
+
+  // string_view + string &&
+   template<typename _CharT, typename _Traits, typename _Alloc>
+    _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
+    inline basic_string<_CharT, _Traits, _Alloc>
+    operator+(__type_identity_t<basic_string_view<_CharT, _Traits>> __lhs,
+	       basic_string<_CharT, _Traits, _Alloc>&& __rhs)
+    {
+      return std::move(__rhs.insert(0, __lhs));
+    }
+#endif
+
   // operator ==
   /**
    *  @brief  Test equivalence of two strings.
diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def
index ad4715048ab..e5cb527728b 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -694,6 +694,11 @@ ftms = {
 
 ftms = {
   name = string_view;
+  values = {
+    v = 202403;
+    cxxmin = 26;
+    hosted = yes;
+  };
   values = {
     v = 201803;
     cxxmin = 17;
diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h
index e35254d8202..b918eda3e8b 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -769,7 +769,12 @@
 #undef __glibcxx_want_shared_ptr_weak_type
 
 #if !defined(__cpp_lib_string_view)
-# if (__cplusplus >= 201703L) && _GLIBCXX_HOSTED
+# if (__cplusplus >  202302L) && _GLIBCXX_HOSTED
+#  define __glibcxx_string_view 202403L
+#  if defined(__glibcxx_want_all) || defined(__glibcxx_want_string_view)
+#   define __cpp_lib_string_view 202403L
+#  endif
+# elif (__cplusplus >= 201703L) && _GLIBCXX_HOSTED
 #  define __glibcxx_string_view 201803L
 #  if defined(__glibcxx_want_all) || defined(__glibcxx_want_string_view)
 #   define __cpp_lib_string_view 201803L
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_fspath_cpp17_fail.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_fspath_cpp17_fail.cc
new file mode 100644
index 00000000000..693d9fd311d
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_fspath_cpp17_fail.cc
@@ -0,0 +1,21 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do compile { target c++17 } }
+// { dg-error "no match for" "P2591" { target c++17 } 25 }
+
+#include "op_plus_fspath_impl.h"
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_fspath_cpp2c_fail.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_fspath_cpp2c_fail.cc
new file mode 100644
index 00000000000..b69cdef73da
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_fspath_cpp2c_fail.cc
@@ -0,0 +1,22 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2c" }
+// { dg-do compile { target c++17 } }
+// { dg-error "no match for" "P2591" { target c++26 } 25 }
+
+#include "op_plus_fspath_impl.h"
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_fspath_impl.h b/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_fspath_impl.h
new file mode 100644
index 00000000000..908c79869e7
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_fspath_impl.h
@@ -0,0 +1,26 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <filesystem>
+#include <string>
+
+int main()
+{
+  std::filesystem::path p = "/var/log/";
+  std::string s = "file";
+  p + s; // { dg-error "no match for" "P2591" }
+}
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_string_view.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_string_view.cc
new file mode 100644
index 00000000000..ef31a70a947
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_string_view.cc
@@ -0,0 +1,187 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++26" }
+// { dg-do run { target c++20 } }
+
+#include <string>
+#include <type_traits>
+#include <utility>
+
+#include <testsuite_hooks.h>
+
+#if !defined(__cpp_lib_string_view) || __cpp_lib_string_view < 202403L
+#error
+#endif
+
+static_assert(std::is_same_v<decltype(std::declval<std::string>() + std::declval<std::string_view>()), std::string>);
+static_assert(std::is_same_v<decltype(std::declval<std::string &>() + std::declval<std::string_view>()), std::string>);
+static_assert(std::is_same_v<decltype(std::declval<std::string_view>() + std::declval<std::string>()), std::string>);
+static_assert(std::is_same_v<decltype(std::declval<std::string_view>() + std::declval<std::string &>()), std::string>);
+
+struct convertible_to_string_view1
+{
+  constexpr operator std::string_view() const { return "convertible_to_sv1"; }
+};
+
+struct convertible_to_string_view2
+{
+  constexpr operator std::string_view()       { return "convertible_to_sv2"; }
+};
+
+struct convertible_to_string_view3
+{
+  constexpr operator std::string_view()       { return "convertible_to_sv3 non_const"; }
+  constexpr operator std::string_view() const { return "convertible_to_sv3 const"; }
+};
+
+struct convertible_to_string_view_and_char_star
+{
+  constexpr operator std::string_view() const { return "convertible_to_sv_and_charstar1"; }
+  constexpr operator const char *() const { return "convertible_to_sv_and_charstar2"; }
+};
+
+struct convertible_to_lots
+{
+  constexpr operator std::string_view() const { return "convertible_to_lots1"; }
+  constexpr operator const char *() const { return "convertible_to_lots2"; }
+  constexpr operator std::string() const { return "convertible_to_lots3"; }
+};
+
+using namespace std::literals;
+static_assert( "costa "s + "marbella"sv == "costa marbella"s );
+static_assert( "costa "sv + "marbella"s == "costa marbella"s );
+static_assert( "costa "s + convertible_to_string_view1{} == "costa convertible_to_sv1"s );
+static_assert( "costa "s + convertible_to_string_view2{} == "costa convertible_to_sv2"s );
+static_assert( "costa "s + convertible_to_string_view3{} == "costa convertible_to_sv3 non_const"s );
+static_assert( "costa "s + convertible_to_string_view_and_char_star{} == "costa convertible_to_sv_and_charstar1"s );
+static_assert( "costa "s + convertible_to_lots{} == "costa convertible_to_lots1"s );
+
+void
+test01()
+{
+  std::string str_0("costa ");
+  std::string str_1("marbella");
+
+  std::string tmp;
+
+  std::string_view str_0_view = str_0;
+  std::string_view str_1_view = str_1;
+
+
+  // string + string_view
+  VERIFY( (str_0 + str_1_view) == "costa marbella" );
+  VERIFY( (str_0 + std::as_const(str_1_view)) == "costa marbella" );
+  VERIFY( (str_0 + std::string_view(str_1)) == "costa marbella" );
+  VERIFY( (str_0_view + str_1) == "costa marbella" );
+  VERIFY( (std::as_const(str_0_view) + str_1) == "costa marbella" );
+  VERIFY( (std::string_view(str_0) + str_1) == "costa marbella" );
+  tmp = str_0;
+  VERIFY( (std::move(tmp) + str_1_view) == "costa marbella" );
+  tmp = str_1;
+  VERIFY( (str_0_view + std::move(tmp)) == "costa marbella" );
+
+
+  // convertible to string_view
+  convertible_to_string_view1 conv_string_view1;
+  VERIFY( (str_0 + conv_string_view1) == "costa convertible_to_sv1" );
+  VERIFY( (str_0 + std::as_const(conv_string_view1)) == "costa convertible_to_sv1" );
+  VERIFY( (std::as_const(str_0) + conv_string_view1) == "costa convertible_to_sv1" );
+  VERIFY( (std::as_const(str_0) + std::as_const(conv_string_view1)) == "costa convertible_to_sv1" );
+
+  tmp = str_0;
+  VERIFY( (std::move(tmp) + conv_string_view1) == "costa convertible_to_sv1" );
+  tmp = str_1;
+  VERIFY( (conv_string_view1 + std::move(tmp)) == "convertible_to_sv1marbella" );
+
+  VERIFY( (conv_string_view1 + str_1) == "convertible_to_sv1marbella" );
+  VERIFY( (conv_string_view1 + std::as_const(str_1)) == "convertible_to_sv1marbella" );
+  VERIFY( (std::as_const(conv_string_view1) + str_1) == "convertible_to_sv1marbella" );
+  VERIFY( (std::as_const(conv_string_view1) + std::as_const(str_1)) == "convertible_to_sv1marbella" );
+
+
+  convertible_to_string_view2 conv_string_view2;
+  VERIFY( (str_0 + conv_string_view2) == "costa convertible_to_sv2" );
+  VERIFY( (std::as_const(str_0) + conv_string_view2) == "costa convertible_to_sv2" );
+  tmp = str_0;
+  VERIFY( (std::move(tmp) + conv_string_view2) == "costa convertible_to_sv2" );
+  tmp = str_1;
+  VERIFY( (conv_string_view2 + std::move(tmp)) == "convertible_to_sv2marbella" );
+
+
+  convertible_to_string_view3 conv_string_view3;
+  VERIFY( (str_0 + conv_string_view3) == "costa convertible_to_sv3 non_const" );
+  VERIFY( (str_0 + std::as_const(conv_string_view3)) == "costa convertible_to_sv3 const" );
+  VERIFY( (std::as_const(str_0) + conv_string_view3) == "costa convertible_to_sv3 non_const" );
+  VERIFY( (std::as_const(str_0) + std::as_const(conv_string_view3)) == "costa convertible_to_sv3 const" );
+
+  tmp = str_0;
+  VERIFY( (std::move(tmp) + conv_string_view3) == "costa convertible_to_sv3 non_const" );
+  tmp = str_1;
+  VERIFY( (conv_string_view3 + std::move(tmp)) == "convertible_to_sv3 non_constmarbella" );
+
+  VERIFY( (conv_string_view3 + str_1) == "convertible_to_sv3 non_constmarbella" );
+  VERIFY( (conv_string_view3 + std::as_const(str_1)) == "convertible_to_sv3 non_constmarbella" );
+  VERIFY( (std::as_const(conv_string_view3) + str_1) == "convertible_to_sv3 constmarbella" );
+  VERIFY( (std::as_const(conv_string_view3) + std::as_const(str_1)) == "convertible_to_sv3 constmarbella" );
+
+
+  convertible_to_string_view_and_char_star conv_sv_cs;
+  VERIFY( (str_0 + conv_sv_cs) == "costa convertible_to_sv_and_charstar1" );
+  VERIFY( (conv_sv_cs + str_1) == "convertible_to_sv_and_charstar1marbella" );
+
+
+  convertible_to_lots conv_lots;
+  VERIFY( (str_0 + conv_lots) == "costa convertible_to_lots1" );
+  VERIFY( (conv_lots + str_1) == "convertible_to_lots1marbella" );
+
+
+  // Check that we're not regressing common cases
+  // string + string literal
+  VERIFY( (str_0 + "marbella") == "costa marbella" );
+  VERIFY( ("costa " + str_1) == "costa marbella" );
+
+  tmp = str_0;
+  VERIFY( (std::move(tmp) + "marbella") == "costa marbella" );
+  tmp = str_1;
+  VERIFY( ("costa " + std::move(tmp)) == "costa marbella" );
+
+
+  // string + non-const char *
+  VERIFY( (str_0 + str_1.data()) == "costa marbella" );
+  VERIFY( (str_0.data() + str_1) == "costa marbella" );
+
+  tmp = str_0;
+  VERIFY( (std::move(tmp) + str_1.data()) == "costa marbella" );
+  tmp = str_1;
+  VERIFY( (str_0.data() + std::move(tmp)) == "costa marbella" );
+
+
+  // string + const char *
+  VERIFY( (str_0 + std::as_const(str_1).data()) == "costa marbella" );
+  VERIFY( (std::as_const(str_0).data() + str_1) == "costa marbella" );
+
+  tmp = str_0;
+  VERIFY( (std::move(tmp) + std::as_const(str_1).data()) == "costa marbella" );
+  tmp = str_1;
+  VERIFY( (std::as_const(str_0).data() + std::move(tmp)) == "costa marbella" );
+}
+
+int main()
+{
+  test01();
+}
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_string_view_compat_fail.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_string_view_compat_fail.cc
new file mode 100644
index 00000000000..3f8349f0450
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_string_view_compat_fail.cc
@@ -0,0 +1,22 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2c" }
+// { dg-do compile { target c++17 } }
+// { dg-error "ambiguous" "P2591" { target c++26 } 73 }
+
+#include "op_plus_string_view_compat_impl.h"
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_string_view_compat_impl.h b/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_string_view_compat_impl.h
new file mode 100644
index 00000000000..4064a1a20e9
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_string_view_compat_impl.h
@@ -0,0 +1,75 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <string>
+#include <type_traits>
+#include <utility>
+
+#include <testsuite_hooks.h>
+
+// "legacy" string view and operators
+template <typename CharT>
+struct basic_my_string_view
+{
+  std::basic_string_view<CharT> view;
+};
+
+using my_string_view = basic_my_string_view<char>;
+
+template <class T>
+struct my_type_identity { using type = T; };
+template <class T>
+using my_type_identity_t = typename my_type_identity<T>::type;
+
+template <typename CharT, typename T, typename A>
+std::string operator+(const std::basic_string<CharT, T, A> &s, basic_my_string_view<CharT> msv)
+{
+  std::string result = s;
+  result += msv.view;
+  result += " using my_string_view";
+  return result;
+}
+
+template <typename CharT, typename T, typename A>
+std::string operator+(const std::basic_string<CharT, T, A> &s, my_type_identity_t<basic_my_string_view<CharT>> msv)
+{
+  std::string result = s;
+  result += msv.view;
+  result += " using my_string_view";
+  return result;
+}
+
+
+struct buffer
+{
+  std::string buf;
+
+  // "legacy"
+  operator my_string_view() const { return my_string_view{buf}; }
+  // "modern"
+  operator std::string_view() const { return std::string_view{buf}; }
+};
+
+int
+main()
+{
+  std::string s = "costa ";
+  buffer b{"marbella"};
+
+  std::string result = s + b;
+  VERIFY( result == "costa marbella using my_string_view" );
+}
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_string_view_compat_ok.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_string_view_compat_ok.cc
new file mode 100644
index 00000000000..8ef3cd25863
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_string_view_compat_ok.cc
@@ -0,0 +1,20 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++17 } }
+
+#include "op_plus_string_view_compat_impl.h"
-- 
2.34.1

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature

Reply via email to