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
smime.p7s
Description: S/MIME Cryptographic Signature