public inbox for libstdc++@gcc.gnu.org
 help / color / mirror / Atom feed
* [committed] libstdc++: Implement string_view range constructor for C++23
@ 2021-03-22 23:16 Jonathan Wakely
  2021-04-27 14:34 ` Stephan Bergmann
  0 siblings, 1 reply; 5+ messages in thread
From: Jonathan Wakely @ 2021-03-22 23:16 UTC (permalink / raw)
  To: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 669 bytes --]

This implements the new string_view constructor proposed by P1989R2.
This hasn't been voted into the C++23 draft yet, but it's been reviewed
by LWG and is expected to be approved at the next WG21 meeting.

libstdc++-v3/ChangeLog:

	* include/std/string_view (basic_string_view(Range&&)): Define new
	constructor and deduction guide.
	* testsuite/21_strings/basic_string_view/cons/char/range_c++20.cc: New test.
	* testsuite/21_strings/basic_string_view/cons/wchar_t/range_c++20.cc: New test.

Tested powerpc64le-linux. Committed to trunk.

(I wrote "C++20" in the commit log summary but it's a C++23 feature,
which is why I'm confortable pushing it now in stage 4.)




[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 13589 bytes --]

commit 7c1006135ddeab216f376adc5f6135a22bfc0ff6
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Mon Mar 22 17:11:21 2021

    libstdc++: Implement string_view range constructor for C++20
    
    This implements the new string_view constructor proposed by P1989R2.
    This hasn't been voted into the C++23 draft yet, but it's been reviewed
    by LWG and is expected to be approved at the next WG21 meeting.
    
    libstdc++-v3/ChangeLog:
    
            * include/std/string_view (basic_string_view(Range&&)): Define new
            constructor and deduction guide.
            * testsuite/21_strings/basic_string_view/cons/char/range_c++20.cc: New test.
            * testsuite/21_strings/basic_string_view/cons/wchar_t/range_c++20.cc: New test.

diff --git a/libstdc++-v3/include/std/string_view b/libstdc++-v3/include/std/string_view
index dba757fad6b..31502f7d58d 100644
--- a/libstdc++-v3/include/std/string_view
+++ b/libstdc++-v3/include/std/string_view
@@ -45,6 +45,10 @@
 #include <bits/ostream_insert.h>
 #include <ext/numeric_traits.h>
 
+#if __cplusplus > 202002L
+# include <bits/ranges_base.h>
+#endif
+
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -135,7 +139,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       : _M_len{__len}, _M_str{__str}
       { }
 
-#if __cplusplus > 201703L && __cpp_lib_concepts
+#if __cplusplus >= 202002L && __cpp_lib_concepts
       template<contiguous_iterator _It, sized_sentinel_for<_It> _End>
 	requires same_as<iter_value_t<_It>, _CharT>
 	  && (!convertible_to<_End, size_type>)
@@ -143,7 +147,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	basic_string_view(_It __first, _End __last)
 	: _M_len(__last - __first), _M_str(std::to_address(__first))
 	{ }
-#endif
+
+#if __cplusplus > 202002L
+      template<typename _Range, typename _DRange = remove_cvref_t<_Range>>
+	requires (!is_same_v<_DRange, basic_string_view>)
+	  && ranges::contiguous_range<_Range>
+	  && ranges::sized_range<_Range>
+	  && is_same_v<ranges::range_value_t<_Range>, _CharT>
+	  && (!is_convertible_v<_Range, const _CharT*>)
+	  && (!requires (_DRange& __d) {
+		__d.operator ::std::basic_string_view<_CharT, _Traits>();
+	      })
+	  && (!requires { typename _DRange::traits_type; }
+	      || is_same_v<typename _DRange::traits_type, _Traits>)
+	constexpr
+	basic_string_view(_Range&& __r)
+	noexcept(noexcept(ranges::size(__r)) && noexcept(ranges::data(__r)))
+	: _M_len(ranges::size(__r)), _M_str(ranges::data(__r))
+	{ }
+#endif // C++23
+#endif // C++20
 
       constexpr basic_string_view&
       operator=(const basic_string_view&) noexcept = default;
@@ -490,6 +513,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #if __cplusplus > 201703L && __cpp_lib_concepts && __cpp_deduction_guides
   template<contiguous_iterator _It, sized_sentinel_for<_It> _End>
     basic_string_view(_It, _End) -> basic_string_view<iter_value_t<_It>>;
+
+#if __cplusplus > 202002L
+  template<ranges::contiguous_range _Range>
+    basic_string_view(_Range&&)
+      -> basic_string_view<ranges::range_value_t<_Range>>;
+#endif
 #endif
 
   // [string.view.comparison], non-member basic_string_view comparison function
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/cons/char/range_c++20.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/cons/char/range_c++20.cc
new file mode 100644
index 00000000000..fa85f1994c9
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/cons/char/range_c++20.cc
@@ -0,0 +1,170 @@
+// Copyright (C) 2021 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++23" }
+// { dg-do run { target c++23 } }
+
+#include <string_view>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  struct R
+  {
+    const char* begin() const
+    { return str; }
+
+    const char* end() const
+    { return str + std::char_traits<char>::length(str); }
+
+    const char* str = "Home on the range";
+  };
+
+  R r;
+  std::string_view s = r;
+  VERIFY( s == r.str );
+  VERIFY( s.data() == std::ranges::data(r) );
+  VERIFY( s.size() == std::ranges::size(r) );
+
+  struct R2 : R
+  {
+    using R::begin;
+    using R::end;
+    operator std::string_view() const { return "Out of range"; }
+  };
+  static_assert( std::ranges::contiguous_range<R2> );
+  static_assert( std::ranges::sized_range<R2> );
+  R2 r2;
+  std::string_view s2 = r2; // uses conversion to string_view
+  VERIFY( s2 == "Out of range" );
+  VERIFY( std::string_view(const_cast<const R2&>(r2)) == s2 );
+
+  struct R3 : R
+  {
+    using R::begin;
+    using R::end;
+    operator const char*() { return "Orange"; }
+  };
+  static_assert( std::ranges::contiguous_range<R3> );
+  static_assert( std::ranges::sized_range<R3> );
+  R3 r3;
+  std::string_view s3(r3); // uses conversion to const char*
+  VERIFY( s3 == "Orange" );
+  s3 = std::string_view(const_cast<const R3&>(r3)); // uses range constructor
+  VERIFY( s3 == "Home on the range" );
+
+  struct R4 : R
+  {
+    using R::begin;
+    using R::end;
+    operator std::string_view() { return "Strange"; }
+  };
+  static_assert( std::ranges::contiguous_range<R4> );
+  static_assert( std::ranges::sized_range<R4> );
+  R4 r4;
+  std::string_view s4 = r4; // Uses conversion to string_view
+  VERIFY( s4 == "Strange" );
+  // Cannot construct from const R4 because of non-const conversion op:
+  static_assert( ! std::is_constructible_v<std::string_view, const R4&> );
+
+  struct R5 : R
+  {
+    using R::begin;
+    using R::end;
+    operator std::string_view() && { return "Stranger"; }
+  };
+  static_assert( std::ranges::contiguous_range<R5> );
+  static_assert( std::ranges::sized_range<R5> );
+  R5 r5;
+  std::string_view s5 = r5; // Uses range constructor
+  VERIFY( s5 == r5.str );
+  s5 = std::string_view(std::move(r5)); // In C++20 this used conversion op.
+  VERIFY( s5 == r5.str );	        // In C++23 it uses range constructor.
+
+  char arr[] = "arrangement\0with\0nulls";
+  std::string_view sa = arr; // Does not use range constructor
+  VERIFY( sa.data() == arr );
+  VERIFY( sa == "arrangement" );
+  VERIFY( std::end(sa) != std::end(arr) );
+}
+
+void
+test02()
+{
+  using V1 = std::basic_string_view<signed char>;
+  // range_value_t<V1> is not the right type
+  static_assert( ! std::is_constructible_v<std::string_view, V1> );
+
+  using V2 = std::basic_string_view<char, __gnu_cxx::char_traits<char>>;
+  // V2::traits_type is not the right type
+  static_assert( ! std::is_constructible_v<std::string_view, V2> );
+
+  struct V3 : V2
+  {
+  private:
+    using V2::traits_type;
+  };
+  // V3::traits_type is not a valid (accessible) type
+  static_assert( std::is_constructible_v<std::string_view, V3> );
+
+  struct V4 : V2
+  {
+    using traits_type = std::string_view::traits_type;
+  };
+  // V4::traits_type is the right type
+  static_assert( std::is_constructible_v<std::string_view, V4> );
+}
+
+void
+test03()
+{
+  struct R
+  {
+    char* begin() { return nullptr; }
+    const char* begin() const noexcept { return nullptr; }
+
+    char* end() { return nullptr; }
+    const char* end() const noexcept { return nullptr; }
+  };
+
+  static_assert( ! noexcept(std::string_view(std::declval<R&>())) );
+  static_assert( noexcept(std::string_view(std::declval<const R&>())) );
+}
+
+void
+test04()
+{
+  struct R
+  {
+    const char* begin() const { return nullptr; }
+    const char* end() const { return nullptr; }
+  };
+
+  R r;
+  std::basic_string_view s = r; // Use deduction guide.
+
+  static_assert( std::is_same_v<decltype(s), std::string_view> );
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+}
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/cons/wchar_t/range_c++20.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/cons/wchar_t/range_c++20.cc
new file mode 100644
index 00000000000..cf73ae36a60
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/cons/wchar_t/range_c++20.cc
@@ -0,0 +1,170 @@
+// Copyright (C) 2021 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++23" }
+// { dg-do run { target c++23 } }
+
+#include <string_view>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  struct R
+  {
+    const wchar_t* begin() const
+    { return str; }
+
+    const wchar_t* end() const
+    { return str + std::char_traits<wchar_t>::length(str); }
+
+    const wchar_t* str = L"Home on the range";
+  };
+
+  R r;
+  std::wstring_view s = r;
+  VERIFY( s == r.str );
+  VERIFY( s.data() == std::ranges::data(r) );
+  VERIFY( s.size() == std::ranges::size(r) );
+
+  struct R2 : R
+  {
+    using R::begin;
+    using R::end;
+    operator std::wstring_view() const { return L"Out of range"; }
+  };
+  static_assert( std::ranges::contiguous_range<R2> );
+  static_assert( std::ranges::sized_range<R2> );
+  R2 r2;
+  std::wstring_view s2 = r2; // uses conversion to wstring_view
+  VERIFY( s2 == L"Out of range" );
+  VERIFY( std::wstring_view(const_cast<const R2&>(r2)) == s2 );
+
+  struct R3 : R
+  {
+    using R::begin;
+    using R::end;
+    operator const wchar_t*() { return L"Orange"; }
+  };
+  static_assert( std::ranges::contiguous_range<R3> );
+  static_assert( std::ranges::sized_range<R3> );
+  R3 r3;
+  std::wstring_view s3(r3); // uses conversion to const wchar_t*
+  VERIFY( s3 == L"Orange" );
+  s3 = std::wstring_view(const_cast<const R3&>(r3)); // uses range constructor
+  VERIFY( s3 == L"Home on the range" );
+
+  struct R4 : R
+  {
+    using R::begin;
+    using R::end;
+    operator std::wstring_view() { return L"Strange"; }
+  };
+  static_assert( std::ranges::contiguous_range<R4> );
+  static_assert( std::ranges::sized_range<R4> );
+  R4 r4;
+  std::wstring_view s4 = r4; // Uses conversion to wstring_view
+  VERIFY( s4 == L"Strange" );
+  // Cannot construct from const R4 because of non-const conversion op:
+  static_assert( ! std::is_constructible_v<std::wstring_view, const R4&> );
+
+  struct R5 : R
+  {
+    using R::begin;
+    using R::end;
+    operator std::wstring_view() && { return L"Stranger"; }
+  };
+  static_assert( std::ranges::contiguous_range<R5> );
+  static_assert( std::ranges::sized_range<R5> );
+  R5 r5;
+  std::wstring_view s5 = r5; // Uses range constructor
+  VERIFY( s5 == r5.str );
+  s5 = std::wstring_view(std::move(r5)); // In C++20 this used conversion op.
+  VERIFY( s5 == r5.str );	        // In C++23 it uses range constructor.
+
+  wchar_t arr[] = L"arrangement\0with\0nulls";
+  std::wstring_view sa = arr; // Does not use range constructor
+  VERIFY( sa.data() == arr );
+  VERIFY( sa == L"arrangement" );
+  VERIFY( std::end(sa) != std::end(arr) );
+}
+
+void
+test02()
+{
+  using V1 = std::basic_string_view<char>;
+  // range_value_t<V1> is not the right type
+  static_assert( ! std::is_constructible_v<std::wstring_view, V1> );
+
+  using V2 = std::basic_string_view<wchar_t, __gnu_cxx::char_traits<wchar_t>>;
+  // V2::traits_type is not the right type
+  static_assert( ! std::is_constructible_v<std::wstring_view, V2> );
+
+  struct V3 : V2
+  {
+  private:
+    using V2::traits_type;
+  };
+  // V3::traits_type is not a valid (accessible) type
+  static_assert( std::is_constructible_v<std::wstring_view, V3> );
+
+  struct V4 : V2
+  {
+    using traits_type = std::wstring_view::traits_type;
+  };
+  // V4::traits_type is the right type
+  static_assert( std::is_constructible_v<std::wstring_view, V4> );
+}
+
+void
+test03()
+{
+  struct R
+  {
+    wchar_t* begin() { return nullptr; }
+    const wchar_t* begin() const noexcept { return nullptr; }
+
+    wchar_t* end() { return nullptr; }
+    const wchar_t* end() const noexcept { return nullptr; }
+  };
+
+  static_assert( ! noexcept(std::wstring_view(std::declval<R&>())) );
+  static_assert( noexcept(std::wstring_view(std::declval<const R&>())) );
+}
+
+void
+test04()
+{
+  struct R
+  {
+    const wchar_t* begin() const { return nullptr; }
+    const wchar_t* end() const { return nullptr; }
+  };
+
+  R r;
+  std::basic_string_view s = r; // Use deduction guide.
+
+  static_assert( std::is_same_v<decltype(s), std::wstring_view> );
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+}

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [committed] libstdc++: Implement string_view range constructor for C++23
  2021-03-22 23:16 [committed] libstdc++: Implement string_view range constructor for C++23 Jonathan Wakely
@ 2021-04-27 14:34 ` Stephan Bergmann
  2021-04-27 16:31   ` Jonathan Wakely
  0 siblings, 1 reply; 5+ messages in thread
From: Stephan Bergmann @ 2021-04-27 14:34 UTC (permalink / raw)
  To: libstdc++; +Cc: Jonathan Wakely

On 23/03/2021 00:16, Jonathan Wakely via Gcc-patches wrote:
> This implements the new string_view constructor proposed by P1989R2.
> This hasn't been voted into the C++23 draft yet, but it's been reviewed
> by LWG and is expected to be approved at the next WG21 meeting.
> 
> libstdc++-v3/ChangeLog:
> 
> 	* include/std/string_view (basic_string_view(Range&&)): Define new
> 	constructor and deduction guide.
> 	* testsuite/21_strings/basic_string_view/cons/char/range_c++20.cc: New test.
> 	* testsuite/21_strings/basic_string_view/cons/wchar_t/range_c++20.cc: New test.
> 
> Tested powerpc64le-linux. Committed to trunk.
> 
> (I wrote "C++20" in the commit log summary but it's a C++23 feature,
> which is why I'm confortable pushing it now in stage 4.)

I observe that with this change, recent Clang 13 trunk with -std=c++2b 
starts to fail on Boost's boost/spirit/include/qi.hpp (at least both 
Boost 1.73 and 1.75).  I unfortunately wasn't able to reduce this to a 
reasonably small testcase, and have no idea whether its a Clang, 
libstdc++, or a even Boost issue.

> $ cat test.cc
> #include "boost/spirit/include/qi.hpp"

> $ ~/llvm/trunk/inst/bin/clang++ --gcc-toolchain=~/gcc/trunk/inst -std=c++2b -fsyntax-only test.cc
> In file included from test.cc:1:
> In file included from /usr/include/boost/spirit/include/qi.hpp:16:
> In file included from /usr/include/boost/spirit/home/qi.hpp:14:
> In file included from /usr/include/boost/spirit/home/qi/action.hpp:14:
> In file included from /usr/include/boost/spirit/home/qi/action/action.hpp:14:
> In file included from /usr/include/boost/spirit/home/qi/meta_compiler.hpp:14:
> In file included from /usr/include/boost/spirit/home/support/meta_compiler.hpp:17:
> In file included from /usr/include/boost/spirit/home/support/make_component.hpp:15:
> In file included from /usr/include/boost/spirit/home/support/detail/make_cons.hpp:16:
> In file included from /usr/include/boost/fusion/include/cons.hpp:10:
> In file included from /usr/include/boost/fusion/support/config.hpp:13:
> In file included from ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/utility:70:
> ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/stl_pair.h:217:11: error: field has incomplete type 'boost::spirit::info'
>       _T1 first;                 ///< The first member
>           ^
> ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/iterator_concepts.h:949:29: note: in instantiation of template class 'std::pair<boost::spirit::info, boost::spirit::info>' requested here
>           { __detail::__decay_copy(begin(__t)) } -> input_or_output_iterator;
>                                    ^
> ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/iterator_concepts.h:949:6: note: in instantiation of requirement here
>           { __detail::__decay_copy(begin(__t)) } -> input_or_output_iterator;
>             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/iterator_concepts.h:947:5: note: while substituting template arguments into constraint expression here
>         && requires(_Tp& __t)
>            ^~~~~~~~~~~~~~~~~~
> ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/ranges_base.h:115:7: note: while checking the satisfaction of concept '__adl_begin<const boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>> &>' requested here
>           || __adl_begin<_Tp>
>              ^~~~~~~~~~~~~~~~
> ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/ranges_base.h:115:7: note: while substituting template arguments into constraint expression here
>           || __adl_begin<_Tp>
>              ^~~~~~~~~~~~~~~~
> ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/ranges_base.h:581:2: note: (skipping 83 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
>         ranges::begin(__t);
>         ^
> /usr/include/boost/mpl/aux_/preprocessed/gcc/and.hpp:50:7: note: in instantiation of template class 'boost::mpl::aux::and_impl<true, boost::mpl::not_<boost::is_const<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>>>>, boost::detail::variant::is_variant_constructible_from<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&, boost::mpl::l_item<mpl_::long_<5>, boost::spirit::info::nil_, boost::mpl::l_item<mpl_::long_<4>, std::basic_string<char>, boost::mpl::l_item<mpl_::long_<3>, boost::recursive_wrapper<boost::spirit::info>, boost::mpl::l_item<mpl_::long_<2>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::mpl::l_item<mpl_::long_<1>, boost::recursive_wrapper<std::list<boost::spirit::info>>, boost::mpl::l_end>>>>>>, mpl_::bool_<true>, mpl_::bool_<true>>' requested here
>     : aux::and_impl<
>       ^
> /usr/include/boost/core/enable_if.hpp:41:41: note: in instantiation of template class 'boost::mpl::and_<boost::is_rvalue_reference<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&>, boost::mpl::not_<boost::is_const<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>>>>, boost::detail::variant::is_variant_constructible_from<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&, boost::mpl::l_item<mpl_::long_<5>, boost::spirit::info::nil_, boost::mpl::l_item<mpl_::long_<4>, std::basic_string<char>, boost::mpl::l_item<mpl_::long_<3>, boost::recursive_wrapper<boost::spirit::info>, boost::mpl::l_item<mpl_::long_<2>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::mpl::l_item<mpl_::long_<1>, boost::recursive_wrapper<std::list<boost::spirit::info>>, boost::mpl::l_end>>>>>>>' requested here
>   struct enable_if : public enable_if_c<Cond::value, T> {};
>                                         ^
> /usr/include/boost/variant/variant.hpp:2136:21: note: in instantiation of template class 'boost::enable_if<boost::mpl::and_<boost::is_rvalue_reference<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&>, boost::mpl::not_<boost::is_const<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>>>>, boost::detail::variant::is_variant_constructible_from<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&, boost::mpl::l_item<mpl_::long_<5>, boost::spirit::info::nil_, boost::mpl::l_item<mpl_::long_<4>, std::basic_string<char>, boost::mpl::l_item<mpl_::long_<3>, boost::recursive_wrapper<boost::spirit::info>, boost::mpl::l_item<mpl_::long_<2>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::mpl::l_item<mpl_::long_<1>, boost::recursive_wrapper<std::list<boost::spirit::info>>, boost::mpl::l_end>>>>>>>, boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &>' requested here
>     typename boost::enable_if<
>                     ^
> /usr/include/boost/variant/variant.hpp:1105:7: note: while substituting deduced template arguments into function template 'operator=' [with T = boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>>]
> class variant
>       ^
> /usr/include/boost/spirit/home/support/info.hpp:29:12: note: while declaring the implicit move assignment operator for 'info'
>     struct info
>            ^
> /usr/include/boost/spirit/home/support/info.hpp:29:12: note: definition of 'boost::spirit::info' is not complete until the closing '}'
> In file included from test.cc:1:
> In file included from /usr/include/boost/spirit/include/qi.hpp:16:
> In file included from /usr/include/boost/spirit/home/qi.hpp:14:
> In file included from /usr/include/boost/spirit/home/qi/action.hpp:14:
> In file included from /usr/include/boost/spirit/home/qi/action/action.hpp:14:
> In file included from /usr/include/boost/spirit/home/qi/meta_compiler.hpp:14:
> In file included from /usr/include/boost/spirit/home/support/meta_compiler.hpp:17:
> In file included from /usr/include/boost/spirit/home/support/make_component.hpp:15:
> In file included from /usr/include/boost/spirit/home/support/detail/make_cons.hpp:16:
> In file included from /usr/include/boost/fusion/include/cons.hpp:10:
> In file included from /usr/include/boost/fusion/support/config.hpp:13:
> In file included from ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/utility:70:
> ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/stl_pair.h:218:11: error: field has incomplete type 'boost::spirit::info'
>       _T2 second;                ///< The second member
>           ^
> /usr/include/boost/spirit/home/support/info.hpp:29:12: note: definition of 'boost::spirit::info' is not complete until the closing '}'
>     struct info
>            ^
> In file included from test.cc:1:
> In file included from /usr/include/boost/spirit/include/qi.hpp:16:
> In file included from /usr/include/boost/spirit/home/qi.hpp:14:
> In file included from /usr/include/boost/spirit/home/qi/action.hpp:14:
> In file included from /usr/include/boost/spirit/home/qi/action/action.hpp:14:
> In file included from /usr/include/boost/spirit/home/qi/meta_compiler.hpp:14:
> In file included from /usr/include/boost/spirit/home/support/meta_compiler.hpp:17:
> In file included from /usr/include/boost/spirit/home/support/make_component.hpp:15:
> In file included from /usr/include/boost/spirit/home/support/detail/make_cons.hpp:16:
> In file included from /usr/include/boost/fusion/include/cons.hpp:10:
> In file included from /usr/include/boost/fusion/support/config.hpp:13:
> In file included from ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/utility:70:
> In file included from ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/stl_pair.h:59:
> In file included from ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/move.h:57:
> ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/type_traits:1060:7: error: static_assert failed due to requirement 'std::__is_complete_or_unbounded(std::__type_identity<boost::spirit::info>{})' "template argument must be a complete class or an unbounded array"
>       static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
>       ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/type_traits:139:26: note: in instantiation of template class 'std::is_copy_assignable<boost::spirit::info>' requested here
>     : public conditional<_B1::value, _B2, _B1>::type
>                          ^
> ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/stl_pair.h:391:3: note: in instantiation of template class 'std::__and_<std::is_copy_assignable<boost::spirit::info>, std::is_copy_assignable<boost::spirit::info>>' requested here
>                 __and_<is_copy_assignable<_T1>,
>                 ^
> ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/iterator_concepts.h:949:29: note: in instantiation of template class 'std::pair<boost::spirit::info, boost::spirit::info>' requested here
>           { __detail::__decay_copy(begin(__t)) } -> input_or_output_iterator;
>                                    ^
> ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/iterator_concepts.h:949:6: note: in instantiation of requirement here
>           { __detail::__decay_copy(begin(__t)) } -> input_or_output_iterator;
>             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/iterator_concepts.h:947:5: note: while substituting template arguments into constraint expression here
>         && requires(_Tp& __t)
>            ^~~~~~~~~~~~~~~~~~
> ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/ranges_base.h:115:7: note: (skipping 85 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
>           || __adl_begin<_Tp>
>              ^
> /usr/include/boost/mpl/aux_/preprocessed/gcc/and.hpp:50:7: note: in instantiation of template class 'boost::mpl::aux::and_impl<true, boost::mpl::not_<boost::is_const<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>>>>, boost::detail::variant::is_variant_constructible_from<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&, boost::mpl::l_item<mpl_::long_<5>, boost::spirit::info::nil_, boost::mpl::l_item<mpl_::long_<4>, std::basic_string<char>, boost::mpl::l_item<mpl_::long_<3>, boost::recursive_wrapper<boost::spirit::info>, boost::mpl::l_item<mpl_::long_<2>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::mpl::l_item<mpl_::long_<1>, boost::recursive_wrapper<std::list<boost::spirit::info>>, boost::mpl::l_end>>>>>>, mpl_::bool_<true>, mpl_::bool_<true>>' requested here
>     : aux::and_impl<
>       ^
> /usr/include/boost/core/enable_if.hpp:41:41: note: in instantiation of template class 'boost::mpl::and_<boost::is_rvalue_reference<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&>, boost::mpl::not_<boost::is_const<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>>>>, boost::detail::variant::is_variant_constructible_from<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&, boost::mpl::l_item<mpl_::long_<5>, boost::spirit::info::nil_, boost::mpl::l_item<mpl_::long_<4>, std::basic_string<char>, boost::mpl::l_item<mpl_::long_<3>, boost::recursive_wrapper<boost::spirit::info>, boost::mpl::l_item<mpl_::long_<2>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::mpl::l_item<mpl_::long_<1>, boost::recursive_wrapper<std::list<boost::spirit::info>>, boost::mpl::l_end>>>>>>>' requested here
>   struct enable_if : public enable_if_c<Cond::value, T> {};
>                                         ^
> /usr/include/boost/variant/variant.hpp:2136:21: note: in instantiation of template class 'boost::enable_if<boost::mpl::and_<boost::is_rvalue_reference<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&>, boost::mpl::not_<boost::is_const<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>>>>, boost::detail::variant::is_variant_constructible_from<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&, boost::mpl::l_item<mpl_::long_<5>, boost::spirit::info::nil_, boost::mpl::l_item<mpl_::long_<4>, std::basic_string<char>, boost::mpl::l_item<mpl_::long_<3>, boost::recursive_wrapper<boost::spirit::info>, boost::mpl::l_item<mpl_::long_<2>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::mpl::l_item<mpl_::long_<1>, boost::recursive_wrapper<std::list<boost::spirit::info>>, boost::mpl::l_end>>>>>>>, boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &>' requested here
>     typename boost::enable_if<
>                     ^
> /usr/include/boost/variant/variant.hpp:1105:7: note: while substituting deduced template arguments into function template 'operator=' [with T = boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>>]
> class variant
>       ^
> /usr/include/boost/spirit/home/support/info.hpp:29:12: note: while declaring the implicit move assignment operator for 'info'
>     struct info
>            ^
> In file included from test.cc:1:
> In file included from /usr/include/boost/spirit/include/qi.hpp:16:
> In file included from /usr/include/boost/spirit/home/qi.hpp:14:
> In file included from /usr/include/boost/spirit/home/qi/action.hpp:14:
> In file included from /usr/include/boost/spirit/home/qi/action/action.hpp:14:
> In file included from /usr/include/boost/spirit/home/qi/meta_compiler.hpp:14:
> In file included from /usr/include/boost/spirit/home/support/meta_compiler.hpp:17:
> In file included from /usr/include/boost/spirit/home/support/make_component.hpp:15:
> In file included from /usr/include/boost/spirit/home/support/detail/make_cons.hpp:16:
> In file included from /usr/include/boost/fusion/include/cons.hpp:10:
> In file included from /usr/include/boost/fusion/support/config.hpp:13:
> In file included from ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/utility:70:
> In file included from ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/stl_pair.h:59:
> In file included from ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/move.h:57:
> ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/type_traits:1081:7: error: static_assert failed due to requirement 'std::__is_complete_or_unbounded(std::__type_identity<boost::spirit::info>{})' "template argument must be a complete class or an unbounded array"
>       static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
>       ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/type_traits:139:26: note: in instantiation of template class 'std::is_move_assignable<boost::spirit::info>' requested here
>     : public conditional<_B1::value, _B2, _B1>::type
>                          ^
> ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/stl_pair.h:402:3: note: in instantiation of template class 'std::__and_<std::is_move_assignable<boost::spirit::info>, std::is_move_assignable<boost::spirit::info>>' requested here
>                 __and_<is_move_assignable<_T1>,
>                 ^
> ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/iterator_concepts.h:949:29: note: in instantiation of template class 'std::pair<boost::spirit::info, boost::spirit::info>' requested here
>           { __detail::__decay_copy(begin(__t)) } -> input_or_output_iterator;
>                                    ^
> ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/iterator_concepts.h:949:6: note: in instantiation of requirement here
>           { __detail::__decay_copy(begin(__t)) } -> input_or_output_iterator;
>             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/iterator_concepts.h:947:5: note: while substituting template arguments into constraint expression here
>         && requires(_Tp& __t)
>            ^~~~~~~~~~~~~~~~~~
> ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/ranges_base.h:115:7: note: (skipping 85 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
>           || __adl_begin<_Tp>
>              ^
> /usr/include/boost/mpl/aux_/preprocessed/gcc/and.hpp:50:7: note: in instantiation of template class 'boost::mpl::aux::and_impl<true, boost::mpl::not_<boost::is_const<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>>>>, boost::detail::variant::is_variant_constructible_from<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&, boost::mpl::l_item<mpl_::long_<5>, boost::spirit::info::nil_, boost::mpl::l_item<mpl_::long_<4>, std::basic_string<char>, boost::mpl::l_item<mpl_::long_<3>, boost::recursive_wrapper<boost::spirit::info>, boost::mpl::l_item<mpl_::long_<2>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::mpl::l_item<mpl_::long_<1>, boost::recursive_wrapper<std::list<boost::spirit::info>>, boost::mpl::l_end>>>>>>, mpl_::bool_<true>, mpl_::bool_<true>>' requested here
>     : aux::and_impl<
>       ^
> /usr/include/boost/core/enable_if.hpp:41:41: note: in instantiation of template class 'boost::mpl::and_<boost::is_rvalue_reference<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&>, boost::mpl::not_<boost::is_const<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>>>>, boost::detail::variant::is_variant_constructible_from<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&, boost::mpl::l_item<mpl_::long_<5>, boost::spirit::info::nil_, boost::mpl::l_item<mpl_::long_<4>, std::basic_string<char>, boost::mpl::l_item<mpl_::long_<3>, boost::recursive_wrapper<boost::spirit::info>, boost::mpl::l_item<mpl_::long_<2>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::mpl::l_item<mpl_::long_<1>, boost::recursive_wrapper<std::list<boost::spirit::info>>, boost::mpl::l_end>>>>>>>' requested here
>   struct enable_if : public enable_if_c<Cond::value, T> {};
>                                         ^
> /usr/include/boost/variant/variant.hpp:2136:21: note: in instantiation of template class 'boost::enable_if<boost::mpl::and_<boost::is_rvalue_reference<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&>, boost::mpl::not_<boost::is_const<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>>>>, boost::detail::variant::is_variant_constructible_from<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&, boost::mpl::l_item<mpl_::long_<5>, boost::spirit::info::nil_, boost::mpl::l_item<mpl_::long_<4>, std::basic_string<char>, boost::mpl::l_item<mpl_::long_<3>, boost::recursive_wrapper<boost::spirit::info>, boost::mpl::l_item<mpl_::long_<2>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::mpl::l_item<mpl_::long_<1>, boost::recursive_wrapper<std::list<boost::spirit::info>>, boost::mpl::l_end>>>>>>>, boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &>' requested here
>     typename boost::enable_if<
>                     ^
> /usr/include/boost/variant/variant.hpp:1105:7: note: while substituting deduced template arguments into function template 'operator=' [with T = boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>>]
> class variant
>       ^
> /usr/include/boost/spirit/home/support/info.hpp:29:12: note: while declaring the implicit move assignment operator for 'info'
>     struct info
>            ^
> 4 errors generated.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [committed] libstdc++: Implement string_view range constructor for C++23
  2021-04-27 14:34 ` Stephan Bergmann
@ 2021-04-27 16:31   ` Jonathan Wakely
  2021-04-27 16:56     ` Jonathan Wakely
  2021-04-27 17:51     ` Patrick Palka
  0 siblings, 2 replies; 5+ messages in thread
From: Jonathan Wakely @ 2021-04-27 16:31 UTC (permalink / raw)
  To: Stephan Bergmann; +Cc: libstdc++

On 27/04/21 16:34 +0200, Stephan Bergmann wrote:
>On 23/03/2021 00:16, Jonathan Wakely via Gcc-patches wrote:
>>This implements the new string_view constructor proposed by P1989R2.
>>This hasn't been voted into the C++23 draft yet, but it's been reviewed
>>by LWG and is expected to be approved at the next WG21 meeting.
>>
>>libstdc++-v3/ChangeLog:
>>
>>	* include/std/string_view (basic_string_view(Range&&)): Define new
>>	constructor and deduction guide.
>>	* testsuite/21_strings/basic_string_view/cons/char/range_c++20.cc: New test.
>>	* testsuite/21_strings/basic_string_view/cons/wchar_t/range_c++20.cc: New test.
>>
>>Tested powerpc64le-linux. Committed to trunk.
>>
>>(I wrote "C++20" in the commit log summary but it's a C++23 feature,
>>which is why I'm confortable pushing it now in stage 4.)
>
>I observe that with this change, recent Clang 13 trunk with -std=c++2b 
>starts to fail on Boost's boost/spirit/include/qi.hpp (at least both 
>Boost 1.73 and 1.75).  I unfortunately wasn't able to reduce this to a 
>reasonably small testcase, and have no idea whether its a Clang, 
>libstdc++, or a even Boost issue.

Thanks for the heads up.

I think this is a recursive constraint problem, where the new
constructor participates in overload resolution so we try to satisfy
its constraints, but those constraints depend on the thing that caused
us to attempt overload resolution for that constructor.

But it's not obvious from the errors what triggers that.

>>$ cat test.cc
>>#include "boost/spirit/include/qi.hpp"
>
>>$ ~/llvm/trunk/inst/bin/clang++ --gcc-toolchain=~/gcc/trunk/inst -std=c++2b -fsyntax-only test.cc
>>In file included from test.cc:1:
>>In file included from /usr/include/boost/spirit/include/qi.hpp:16:
>>In file included from /usr/include/boost/spirit/home/qi.hpp:14:
>>In file included from /usr/include/boost/spirit/home/qi/action.hpp:14:
>>In file included from /usr/include/boost/spirit/home/qi/action/action.hpp:14:
>>In file included from /usr/include/boost/spirit/home/qi/meta_compiler.hpp:14:
>>In file included from /usr/include/boost/spirit/home/support/meta_compiler.hpp:17:
>>In file included from /usr/include/boost/spirit/home/support/make_component.hpp:15:
>>In file included from /usr/include/boost/spirit/home/support/detail/make_cons.hpp:16:
>>In file included from /usr/include/boost/fusion/include/cons.hpp:10:
>>In file included from /usr/include/boost/fusion/support/config.hpp:13:
>>In file included from ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/utility:70:
>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/stl_pair.h:217:11: error: field has incomplete type 'boost::spirit::info'
>>      _T1 first;                 ///< The first member
>>          ^
>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/iterator_concepts.h:949:29: note: in instantiation of template class 'std::pair<boost::spirit::info, boost::spirit::info>' requested here
>>          { __detail::__decay_copy(begin(__t)) } -> input_or_output_iterator;
>>                                   ^
>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/iterator_concepts.h:949:6: note: in instantiation of requirement here
>>          { __detail::__decay_copy(begin(__t)) } -> input_or_output_iterator;
>>            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/iterator_concepts.h:947:5: note: while substituting template arguments into constraint expression here
>>        && requires(_Tp& __t)
>>           ^~~~~~~~~~~~~~~~~~
>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/ranges_base.h:115:7: note: while checking the satisfaction of concept '__adl_begin<const boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>> &>' requested here
>>          || __adl_begin<_Tp>
>>             ^~~~~~~~~~~~~~~~
>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/ranges_base.h:115:7: note: while substituting template arguments into constraint expression here
>>          || __adl_begin<_Tp>
>>             ^~~~~~~~~~~~~~~~
>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/ranges_base.h:581:2: note: (skipping 83 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
>>        ranges::begin(__t);
>>        ^
>>/usr/include/boost/mpl/aux_/preprocessed/gcc/and.hpp:50:7: note: in instantiation of template class 'boost::mpl::aux::and_impl<true, boost::mpl::not_<boost::is_const<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>>>>, boost::detail::variant::is_variant_constructible_from<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&, boost::mpl::l_item<mpl_::long_<5>, boost::spirit::info::nil_, boost::mpl::l_item<mpl_::long_<4>, std::basic_string<char>, boost::mpl::l_item<mpl_::long_<3>, boost::recursive_wrapper<boost::spirit::info>, boost::mpl::l_item<mpl_::long_<2>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::mpl::l_item<mpl_::long_<1>, boost::recursive_wrapper<std::list<boost::spirit::info>>, boost::mpl::l_end>>>>>>, mpl_::bool_<true>, mpl_::bool_<true>>' requested here
>>    : aux::and_impl<
>>      ^
>>/usr/include/boost/core/enable_if.hpp:41:41: note: in instantiation of template class 'boost::mpl::and_<boost::is_rvalue_reference<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&>, boost::mpl::not_<boost::is_const<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>>>>, boost::detail::variant::is_variant_constructible_from<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&, boost::mpl::l_item<mpl_::long_<5>, boost::spirit::info::nil_, boost::mpl::l_item<mpl_::long_<4>, std::basic_string<char>, boost::mpl::l_item<mpl_::long_<3>, boost::recursive_wrapper<boost::spirit::info>, boost::mpl::l_item<mpl_::long_<2>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::mpl::l_item<mpl_::long_<1>, boost::recursive_wrapper<std::list<boost::spirit::info>>, boost::mpl::l_end>>>>>>>' requested here
>>  struct enable_if : public enable_if_c<Cond::value, T> {};
>>                                        ^
>>/usr/include/boost/variant/variant.hpp:2136:21: note: in instantiation of template class 'boost::enable_if<boost::mpl::and_<boost::is_rvalue_reference<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&>, boost::mpl::not_<boost::is_const<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>>>>, boost::detail::variant::is_variant_constructible_from<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&, boost::mpl::l_item<mpl_::long_<5>, boost::spirit::info::nil_, boost::mpl::l_item<mpl_::long_<4>, std::basic_string<char>, boost::mpl::l_item<mpl_::long_<3>, boost::recursive_wrapper<boost::spirit::info>, boost::mpl::l_item<mpl_::long_<2>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::mpl::l_item<mpl_::long_<1>, boost::recursive_wrapper<std::list<boost::spirit::info>>, boost::mpl::l_end>>>>>>>, boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &>' requested here
>>    typename boost::enable_if<
>>                    ^
>>/usr/include/boost/variant/variant.hpp:1105:7: note: while substituting deduced template arguments into function template 'operator=' [with T = boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>>]
>>class variant
>>      ^
>>/usr/include/boost/spirit/home/support/info.hpp:29:12: note: while declaring the implicit move assignment operator for 'info'
>>    struct info
>>           ^
>>/usr/include/boost/spirit/home/support/info.hpp:29:12: note: definition of 'boost::spirit::info' is not complete until the closing '}'
>>In file included from test.cc:1:
>>In file included from /usr/include/boost/spirit/include/qi.hpp:16:
>>In file included from /usr/include/boost/spirit/home/qi.hpp:14:
>>In file included from /usr/include/boost/spirit/home/qi/action.hpp:14:
>>In file included from /usr/include/boost/spirit/home/qi/action/action.hpp:14:
>>In file included from /usr/include/boost/spirit/home/qi/meta_compiler.hpp:14:
>>In file included from /usr/include/boost/spirit/home/support/meta_compiler.hpp:17:
>>In file included from /usr/include/boost/spirit/home/support/make_component.hpp:15:
>>In file included from /usr/include/boost/spirit/home/support/detail/make_cons.hpp:16:
>>In file included from /usr/include/boost/fusion/include/cons.hpp:10:
>>In file included from /usr/include/boost/fusion/support/config.hpp:13:
>>In file included from ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/utility:70:
>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/stl_pair.h:218:11: error: field has incomplete type 'boost::spirit::info'
>>      _T2 second;                ///< The second member
>>          ^
>>/usr/include/boost/spirit/home/support/info.hpp:29:12: note: definition of 'boost::spirit::info' is not complete until the closing '}'
>>    struct info
>>           ^
>>In file included from test.cc:1:
>>In file included from /usr/include/boost/spirit/include/qi.hpp:16:
>>In file included from /usr/include/boost/spirit/home/qi.hpp:14:
>>In file included from /usr/include/boost/spirit/home/qi/action.hpp:14:
>>In file included from /usr/include/boost/spirit/home/qi/action/action.hpp:14:
>>In file included from /usr/include/boost/spirit/home/qi/meta_compiler.hpp:14:
>>In file included from /usr/include/boost/spirit/home/support/meta_compiler.hpp:17:
>>In file included from /usr/include/boost/spirit/home/support/make_component.hpp:15:
>>In file included from /usr/include/boost/spirit/home/support/detail/make_cons.hpp:16:
>>In file included from /usr/include/boost/fusion/include/cons.hpp:10:
>>In file included from /usr/include/boost/fusion/support/config.hpp:13:
>>In file included from ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/utility:70:
>>In file included from ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/stl_pair.h:59:
>>In file included from ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/move.h:57:
>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/type_traits:1060:7: error: static_assert failed due to requirement 'std::__is_complete_or_unbounded(std::__type_identity<boost::spirit::info>{})' "template argument must be a complete class or an unbounded array"
>>      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
>>      ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/type_traits:139:26: note: in instantiation of template class 'std::is_copy_assignable<boost::spirit::info>' requested here
>>    : public conditional<_B1::value, _B2, _B1>::type
>>                         ^
>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/stl_pair.h:391:3: note: in instantiation of template class 'std::__and_<std::is_copy_assignable<boost::spirit::info>, std::is_copy_assignable<boost::spirit::info>>' requested here
>>                __and_<is_copy_assignable<_T1>,
>>                ^
>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/iterator_concepts.h:949:29: note: in instantiation of template class 'std::pair<boost::spirit::info, boost::spirit::info>' requested here
>>          { __detail::__decay_copy(begin(__t)) } -> input_or_output_iterator;
>>                                   ^
>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/iterator_concepts.h:949:6: note: in instantiation of requirement here
>>          { __detail::__decay_copy(begin(__t)) } -> input_or_output_iterator;
>>            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/iterator_concepts.h:947:5: note: while substituting template arguments into constraint expression here
>>        && requires(_Tp& __t)
>>           ^~~~~~~~~~~~~~~~~~
>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/ranges_base.h:115:7: note: (skipping 85 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
>>          || __adl_begin<_Tp>
>>             ^
>>/usr/include/boost/mpl/aux_/preprocessed/gcc/and.hpp:50:7: note: in instantiation of template class 'boost::mpl::aux::and_impl<true, boost::mpl::not_<boost::is_const<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>>>>, boost::detail::variant::is_variant_constructible_from<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&, boost::mpl::l_item<mpl_::long_<5>, boost::spirit::info::nil_, boost::mpl::l_item<mpl_::long_<4>, std::basic_string<char>, boost::mpl::l_item<mpl_::long_<3>, boost::recursive_wrapper<boost::spirit::info>, boost::mpl::l_item<mpl_::long_<2>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::mpl::l_item<mpl_::long_<1>, boost::recursive_wrapper<std::list<boost::spirit::info>>, boost::mpl::l_end>>>>>>, mpl_::bool_<true>, mpl_::bool_<true>>' requested here
>>    : aux::and_impl<
>>      ^
>>/usr/include/boost/core/enable_if.hpp:41:41: note: in instantiation of template class 'boost::mpl::and_<boost::is_rvalue_reference<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&>, boost::mpl::not_<boost::is_const<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>>>>, boost::detail::variant::is_variant_constructible_from<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&, boost::mpl::l_item<mpl_::long_<5>, boost::spirit::info::nil_, boost::mpl::l_item<mpl_::long_<4>, std::basic_string<char>, boost::mpl::l_item<mpl_::long_<3>, boost::recursive_wrapper<boost::spirit::info>, boost::mpl::l_item<mpl_::long_<2>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::mpl::l_item<mpl_::long_<1>, boost::recursive_wrapper<std::list<boost::spirit::info>>, boost::mpl::l_end>>>>>>>' requested here
>>  struct enable_if : public enable_if_c<Cond::value, T> {};
>>                                        ^
>>/usr/include/boost/variant/variant.hpp:2136:21: note: in instantiation of template class 'boost::enable_if<boost::mpl::and_<boost::is_rvalue_reference<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&>, boost::mpl::not_<boost::is_const<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>>>>, boost::detail::variant::is_variant_constructible_from<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&, boost::mpl::l_item<mpl_::long_<5>, boost::spirit::info::nil_, boost::mpl::l_item<mpl_::long_<4>, std::basic_string<char>, boost::mpl::l_item<mpl_::long_<3>, boost::recursive_wrapper<boost::spirit::info>, boost::mpl::l_item<mpl_::long_<2>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::mpl::l_item<mpl_::long_<1>, boost::recursive_wrapper<std::list<boost::spirit::info>>, boost::mpl::l_end>>>>>>>, boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &>' requested here
>>    typename boost::enable_if<
>>                    ^
>>/usr/include/boost/variant/variant.hpp:1105:7: note: while substituting deduced template arguments into function template 'operator=' [with T = boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>>]
>>class variant
>>      ^
>>/usr/include/boost/spirit/home/support/info.hpp:29:12: note: while declaring the implicit move assignment operator for 'info'
>>    struct info
>>           ^
>>In file included from test.cc:1:
>>In file included from /usr/include/boost/spirit/include/qi.hpp:16:
>>In file included from /usr/include/boost/spirit/home/qi.hpp:14:
>>In file included from /usr/include/boost/spirit/home/qi/action.hpp:14:
>>In file included from /usr/include/boost/spirit/home/qi/action/action.hpp:14:
>>In file included from /usr/include/boost/spirit/home/qi/meta_compiler.hpp:14:
>>In file included from /usr/include/boost/spirit/home/support/meta_compiler.hpp:17:
>>In file included from /usr/include/boost/spirit/home/support/make_component.hpp:15:
>>In file included from /usr/include/boost/spirit/home/support/detail/make_cons.hpp:16:
>>In file included from /usr/include/boost/fusion/include/cons.hpp:10:
>>In file included from /usr/include/boost/fusion/support/config.hpp:13:
>>In file included from ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/utility:70:
>>In file included from ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/stl_pair.h:59:
>>In file included from ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/move.h:57:
>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/type_traits:1081:7: error: static_assert failed due to requirement 'std::__is_complete_or_unbounded(std::__type_identity<boost::spirit::info>{})' "template argument must be a complete class or an unbounded array"
>>      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
>>      ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/type_traits:139:26: note: in instantiation of template class 'std::is_move_assignable<boost::spirit::info>' requested here
>>    : public conditional<_B1::value, _B2, _B1>::type
>>                         ^
>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/stl_pair.h:402:3: note: in instantiation of template class 'std::__and_<std::is_move_assignable<boost::spirit::info>, std::is_move_assignable<boost::spirit::info>>' requested here
>>                __and_<is_move_assignable<_T1>,
>>                ^
>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/iterator_concepts.h:949:29: note: in instantiation of template class 'std::pair<boost::spirit::info, boost::spirit::info>' requested here
>>          { __detail::__decay_copy(begin(__t)) } -> input_or_output_iterator;
>>                                   ^
>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/iterator_concepts.h:949:6: note: in instantiation of requirement here
>>          { __detail::__decay_copy(begin(__t)) } -> input_or_output_iterator;
>>            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/iterator_concepts.h:947:5: note: while substituting template arguments into constraint expression here
>>        && requires(_Tp& __t)
>>           ^~~~~~~~~~~~~~~~~~
>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/ranges_base.h:115:7: note: (skipping 85 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
>>          || __adl_begin<_Tp>
>>             ^
>>/usr/include/boost/mpl/aux_/preprocessed/gcc/and.hpp:50:7: note: in instantiation of template class 'boost::mpl::aux::and_impl<true, boost::mpl::not_<boost::is_const<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>>>>, boost::detail::variant::is_variant_constructible_from<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&, boost::mpl::l_item<mpl_::long_<5>, boost::spirit::info::nil_, boost::mpl::l_item<mpl_::long_<4>, std::basic_string<char>, boost::mpl::l_item<mpl_::long_<3>, boost::recursive_wrapper<boost::spirit::info>, boost::mpl::l_item<mpl_::long_<2>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::mpl::l_item<mpl_::long_<1>, boost::recursive_wrapper<std::list<boost::spirit::info>>, boost::mpl::l_end>>>>>>, mpl_::bool_<true>, mpl_::bool_<true>>' requested here
>>    : aux::and_impl<
>>      ^
>>/usr/include/boost/core/enable_if.hpp:41:41: note: in instantiation of template class 'boost::mpl::and_<boost::is_rvalue_reference<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&>, boost::mpl::not_<boost::is_const<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>>>>, boost::detail::variant::is_variant_constructible_from<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&, boost::mpl::l_item<mpl_::long_<5>, boost::spirit::info::nil_, boost::mpl::l_item<mpl_::long_<4>, std::basic_string<char>, boost::mpl::l_item<mpl_::long_<3>, boost::recursive_wrapper<boost::spirit::info>, boost::mpl::l_item<mpl_::long_<2>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::mpl::l_item<mpl_::long_<1>, boost::recursive_wrapper<std::list<boost::spirit::info>>, boost::mpl::l_end>>>>>>>' requested here
>>  struct enable_if : public enable_if_c<Cond::value, T> {};
>>                                        ^
>>/usr/include/boost/variant/variant.hpp:2136:21: note: in instantiation of template class 'boost::enable_if<boost::mpl::and_<boost::is_rvalue_reference<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&>, boost::mpl::not_<boost::is_const<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>>>>, boost::detail::variant::is_variant_constructible_from<boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &&, boost::mpl::l_item<mpl_::long_<5>, boost::spirit::info::nil_, boost::mpl::l_item<mpl_::long_<4>, std::basic_string<char>, boost::mpl::l_item<mpl_::long_<3>, boost::recursive_wrapper<boost::spirit::info>, boost::mpl::l_item<mpl_::long_<2>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::mpl::l_item<mpl_::long_<1>, boost::recursive_wrapper<std::list<boost::spirit::info>>, boost::mpl::l_end>>>>>>>, boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>> &>' requested here
>>    typename boost::enable_if<
>>                    ^
>>/usr/include/boost/variant/variant.hpp:1105:7: note: while substituting deduced template arguments into function template 'operator=' [with T = boost::variant<boost::spirit::info::nil_, std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>, boost::recursive_wrapper<std::pair<boost::spirit::info, boost::spirit::info>>, boost::recursive_wrapper<std::list<boost::spirit::info>>>]
>>class variant
>>      ^
>>/usr/include/boost/spirit/home/support/info.hpp:29:12: note: while declaring the implicit move assignment operator for 'info'
>>    struct info
>>           ^
>>4 errors generated.


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [committed] libstdc++: Implement string_view range constructor for C++23
  2021-04-27 16:31   ` Jonathan Wakely
@ 2021-04-27 16:56     ` Jonathan Wakely
  2021-04-27 17:51     ` Patrick Palka
  1 sibling, 0 replies; 5+ messages in thread
From: Jonathan Wakely @ 2021-04-27 16:56 UTC (permalink / raw)
  To: Stephan Bergmann; +Cc: libstdc++

On 27/04/21 17:31 +0100, Jonathan Wakely wrote:
>On 27/04/21 16:34 +0200, Stephan Bergmann wrote:
>>On 23/03/2021 00:16, Jonathan Wakely via Gcc-patches wrote:
>>>This implements the new string_view constructor proposed by P1989R2.
>>>This hasn't been voted into the C++23 draft yet, but it's been reviewed
>>>by LWG and is expected to be approved at the next WG21 meeting.
>>>
>>>libstdc++-v3/ChangeLog:
>>>
>>>	* include/std/string_view (basic_string_view(Range&&)): Define new
>>>	constructor and deduction guide.
>>>	* testsuite/21_strings/basic_string_view/cons/char/range_c++20.cc: New test.
>>>	* testsuite/21_strings/basic_string_view/cons/wchar_t/range_c++20.cc: New test.
>>>
>>>Tested powerpc64le-linux. Committed to trunk.
>>>
>>>(I wrote "C++20" in the commit log summary but it's a C++23 feature,
>>>which is why I'm confortable pushing it now in stage 4.)
>>
>>I observe that with this change, recent Clang 13 trunk with 
>>-std=c++2b starts to fail on Boost's boost/spirit/include/qi.hpp (at 
>>least both Boost 1.73 and 1.75).  I unfortunately wasn't able to 
>>reduce this to a reasonably small testcase, and have no idea whether 
>>its a Clang, libstdc++, or a even Boost issue.
>
>Thanks for the heads up.
>
>I think this is a recursive constraint problem, where the new
>constructor participates in overload resolution so we try to satisfy
>its constraints, but those constraints depend on the thing that caused
>us to attempt overload resolution for that constructor.
>
>But it's not obvious from the errors what triggers that.

It's trying to see if a spirit::info is convertible to std::string,
which considers this constructor:

basic_string(const T&, const Alloc& = Alloc());

That is constructor (10) at:
https://en.cppreference.com/w/cpp/string/basic_string/basic_string
that is constrained by:

std::is_convertible_v<const T&, std::basic_string_view<CharT, Traits>>
is true and std::is_convertible_v<const T&, const CharT*> is false.

Where T is pair<spirit::info, spirit::info>.

To see if the constructor is viable, we check if pair<spirit::info, spirit::info>
can be converted to std::string_view, which considers the new constructor,
which needs to check if that pair is a range. Somewhere deep in the
range requirements we require that is_move_assignable<pair<>> is
true, so we can do DECAY-COPY(begin(r)), which is ill-formed because the
spirit::info type is incomplete, because we're still in its class definition.

We've seen problems like this before. It's nasty.



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [committed] libstdc++: Implement string_view range constructor for C++23
  2021-04-27 16:31   ` Jonathan Wakely
  2021-04-27 16:56     ` Jonathan Wakely
@ 2021-04-27 17:51     ` Patrick Palka
  1 sibling, 0 replies; 5+ messages in thread
From: Patrick Palka @ 2021-04-27 17:51 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: Stephan Bergmann, libstdc++

On Tue, 27 Apr 2021, Jonathan Wakely via Libstdc++ wrote:

> On 27/04/21 16:34 +0200, Stephan Bergmann wrote:
> > On 23/03/2021 00:16, Jonathan Wakely via Gcc-patches wrote:
> > > This implements the new string_view constructor proposed by P1989R2.
> > > This hasn't been voted into the C++23 draft yet, but it's been reviewed
> > > by LWG and is expected to be approved at the next WG21 meeting.
> > > 
> > > libstdc++-v3/ChangeLog:
> > > 
> > > 	* include/std/string_view (basic_string_view(Range&&)): Define new
> > > 	constructor and deduction guide.
> > > 	* testsuite/21_strings/basic_string_view/cons/char/range_c++20.cc: New
> > > test.
> > > 	* testsuite/21_strings/basic_string_view/cons/wchar_t/range_c++20.cc:
> > > New test.
> > > 
> > > Tested powerpc64le-linux. Committed to trunk.
> > > 
> > > (I wrote "C++20" in the commit log summary but it's a C++23 feature,
> > > which is why I'm confortable pushing it now in stage 4.)
> > 
> > I observe that with this change, recent Clang 13 trunk with -std=c++2b
> > starts to fail on Boost's boost/spirit/include/qi.hpp (at least both Boost
> > 1.73 and 1.75).  I unfortunately wasn't able to reduce this to a reasonably
> > small testcase, and have no idea whether its a Clang, libstdc++, or a even
> > Boost issue.
> 
> Thanks for the heads up.
> 
> I think this is a recursive constraint problem, where the new
> constructor participates in overload resolution so we try to satisfy
> its constraints, but those constraints depend on the thing that caused
> us to attempt overload resolution for that constructor.
> 
> But it's not obvious from the errors what triggers that.

It could be a manifestation of the Clang concepts bug
https://bugs.llvm.org/show_bug.cgi?id=44833 -- Clang apparently doesn't
perform deferred substitution into constraints.

> 
> > > $ cat test.cc
> > > #include "boost/spirit/include/qi.hpp"
> > 
> > > $ ~/llvm/trunk/inst/bin/clang++ --gcc-toolchain=~/gcc/trunk/inst
> > > -std=c++2b -fsyntax-only test.cc
> > > In file included from test.cc:1:
> > > In file included from /usr/include/boost/spirit/include/qi.hpp:16:
> > > In file included from /usr/include/boost/spirit/home/qi.hpp:14:
> > > In file included from /usr/include/boost/spirit/home/qi/action.hpp:14:
> > > In file included from
> > > /usr/include/boost/spirit/home/qi/action/action.hpp:14:
> > > In file included from
> > > /usr/include/boost/spirit/home/qi/meta_compiler.hpp:14:
> > > In file included from
> > > /usr/include/boost/spirit/home/support/meta_compiler.hpp:17:
> > > In file included from
> > > /usr/include/boost/spirit/home/support/make_component.hpp:15:
> > > In file included from
> > > /usr/include/boost/spirit/home/support/detail/make_cons.hpp:16:
> > > In file included from /usr/include/boost/fusion/include/cons.hpp:10:
> > > In file included from /usr/include/boost/fusion/support/config.hpp:13:
> > > In file included from
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/utility:70:
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/stl_pair.h:217:11:
> > > error: field has incomplete type 'boost::spirit::info'
> > >      _T1 first;                 ///< The first member
> > >          ^
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/iterator_concepts.h:949:29:
> > > note: in instantiation of template class 'std::pair<boost::spirit::info,
> > > boost::spirit::info>' requested here
> > >          { __detail::__decay_copy(begin(__t)) } ->
> > > input_or_output_iterator;
> > >                                   ^
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/iterator_concepts.h:949:6:
> > > note: in instantiation of requirement here
> > >          { __detail::__decay_copy(begin(__t)) } ->
> > > input_or_output_iterator;
> > >            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/iterator_concepts.h:947:5:
> > > note: while substituting template arguments into constraint expression
> > > here
> > >        && requires(_Tp& __t)
> > >           ^~~~~~~~~~~~~~~~~~
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/ranges_base.h:115:7:
> > > note: while checking the satisfaction of concept '__adl_begin<const
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>> &>' requested here
> > >          || __adl_begin<_Tp>
> > >             ^~~~~~~~~~~~~~~~
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/ranges_base.h:115:7:
> > > note: while substituting template arguments into constraint expression
> > > here
> > >          || __adl_begin<_Tp>
> > >             ^~~~~~~~~~~~~~~~
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/ranges_base.h:581:2:
> > > note: (skipping 83 contexts in backtrace; use -ftemplate-backtrace-limit=0
> > > to see all)
> > >        ranges::begin(__t);
> > >        ^
> > > /usr/include/boost/mpl/aux_/preprocessed/gcc/and.hpp:50:7: note: in
> > > instantiation of template class 'boost::mpl::aux::and_impl<true,
> > > boost::mpl::not_<boost::is_const<boost::variant<boost::spirit::info::nil_,
> > > std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>>>>,
> > > boost::detail::variant::is_variant_constructible_from<boost::variant<boost::spirit::info::nil_,
> > > std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>> &&,
> > > boost::mpl::l_item<mpl_::long_<5>, boost::spirit::info::nil_,
> > > boost::mpl::l_item<mpl_::long_<4>, std::basic_string<char>,
> > > boost::mpl::l_item<mpl_::long_<3>,
> > > boost::recursive_wrapper<boost::spirit::info>,
> > > boost::mpl::l_item<mpl_::long_<2>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>, boost::mpl::l_item<mpl_::long_<1>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>,
> > > boost::mpl::l_end>>>>>>, mpl_::bool_<true>, mpl_::bool_<true>>' requested
> > > here
> > >    : aux::and_impl<
> > >      ^
> > > /usr/include/boost/core/enable_if.hpp:41:41: note: in instantiation of
> > > template class
> > > 'boost::mpl::and_<boost::is_rvalue_reference<boost::variant<boost::spirit::info::nil_,
> > > std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>> &&>,
> > > boost::mpl::not_<boost::is_const<boost::variant<boost::spirit::info::nil_,
> > > std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>>>>,
> > > boost::detail::variant::is_variant_constructible_from<boost::variant<boost::spirit::info::nil_,
> > > std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>> &&,
> > > boost::mpl::l_item<mpl_::long_<5>, boost::spirit::info::nil_,
> > > boost::mpl::l_item<mpl_::long_<4>, std::basic_string<char>,
> > > boost::mpl::l_item<mpl_::long_<3>,
> > > boost::recursive_wrapper<boost::spirit::info>,
> > > boost::mpl::l_item<mpl_::long_<2>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>, boost::mpl::l_item<mpl_::long_<1>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>,
> > > boost::mpl::l_end>>>>>>>' requested here
> > >  struct enable_if : public enable_if_c<Cond::value, T> {};
> > >                                        ^
> > > /usr/include/boost/variant/variant.hpp:2136:21: note: in instantiation of
> > > template class
> > > 'boost::enable_if<boost::mpl::and_<boost::is_rvalue_reference<boost::variant<boost::spirit::info::nil_,
> > > std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>> &&>,
> > > boost::mpl::not_<boost::is_const<boost::variant<boost::spirit::info::nil_,
> > > std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>>>>,
> > > boost::detail::variant::is_variant_constructible_from<boost::variant<boost::spirit::info::nil_,
> > > std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>> &&,
> > > boost::mpl::l_item<mpl_::long_<5>, boost::spirit::info::nil_,
> > > boost::mpl::l_item<mpl_::long_<4>, std::basic_string<char>,
> > > boost::mpl::l_item<mpl_::long_<3>,
> > > boost::recursive_wrapper<boost::spirit::info>,
> > > boost::mpl::l_item<mpl_::long_<2>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>, boost::mpl::l_item<mpl_::long_<1>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>,
> > > boost::mpl::l_end>>>>>>>, boost::variant<boost::spirit::info::nil_,
> > > std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>> &>' requested
> > > here
> > >    typename boost::enable_if<
> > >                    ^
> > > /usr/include/boost/variant/variant.hpp:1105:7: note: while substituting
> > > deduced template arguments into function template 'operator=' [with T =
> > > boost::variant<boost::spirit::info::nil_, std::basic_string<char>,
> > > boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>>]
> > > class variant
> > >      ^
> > > /usr/include/boost/spirit/home/support/info.hpp:29:12: note: while
> > > declaring the implicit move assignment operator for 'info'
> > >    struct info
> > >           ^
> > > /usr/include/boost/spirit/home/support/info.hpp:29:12: note: definition of
> > > 'boost::spirit::info' is not complete until the closing '}'
> > > In file included from test.cc:1:
> > > In file included from /usr/include/boost/spirit/include/qi.hpp:16:
> > > In file included from /usr/include/boost/spirit/home/qi.hpp:14:
> > > In file included from /usr/include/boost/spirit/home/qi/action.hpp:14:
> > > In file included from
> > > /usr/include/boost/spirit/home/qi/action/action.hpp:14:
> > > In file included from
> > > /usr/include/boost/spirit/home/qi/meta_compiler.hpp:14:
> > > In file included from
> > > /usr/include/boost/spirit/home/support/meta_compiler.hpp:17:
> > > In file included from
> > > /usr/include/boost/spirit/home/support/make_component.hpp:15:
> > > In file included from
> > > /usr/include/boost/spirit/home/support/detail/make_cons.hpp:16:
> > > In file included from /usr/include/boost/fusion/include/cons.hpp:10:
> > > In file included from /usr/include/boost/fusion/support/config.hpp:13:
> > > In file included from
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/utility:70:
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/stl_pair.h:218:11:
> > > error: field has incomplete type 'boost::spirit::info'
> > >      _T2 second;                ///< The second member
> > >          ^
> > > /usr/include/boost/spirit/home/support/info.hpp:29:12: note: definition of
> > > 'boost::spirit::info' is not complete until the closing '}'
> > >    struct info
> > >           ^
> > > In file included from test.cc:1:
> > > In file included from /usr/include/boost/spirit/include/qi.hpp:16:
> > > In file included from /usr/include/boost/spirit/home/qi.hpp:14:
> > > In file included from /usr/include/boost/spirit/home/qi/action.hpp:14:
> > > In file included from
> > > /usr/include/boost/spirit/home/qi/action/action.hpp:14:
> > > In file included from
> > > /usr/include/boost/spirit/home/qi/meta_compiler.hpp:14:
> > > In file included from
> > > /usr/include/boost/spirit/home/support/meta_compiler.hpp:17:
> > > In file included from
> > > /usr/include/boost/spirit/home/support/make_component.hpp:15:
> > > In file included from
> > > /usr/include/boost/spirit/home/support/detail/make_cons.hpp:16:
> > > In file included from /usr/include/boost/fusion/include/cons.hpp:10:
> > > In file included from /usr/include/boost/fusion/support/config.hpp:13:
> > > In file included from
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/utility:70:
> > > In file included from
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/stl_pair.h:59:
> > > In file included from
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/move.h:57:
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/type_traits:1060:7:
> > > error: static_assert failed due to requirement
> > > 'std::__is_complete_or_unbounded(std::__type_identity<boost::spirit::info>{})'
> > > "template argument must be a complete class or an unbounded array"
> > >      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
> > >      ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/type_traits:139:26:
> > > note: in instantiation of template class
> > > 'std::is_copy_assignable<boost::spirit::info>' requested here
> > >    : public conditional<_B1::value, _B2, _B1>::type
> > >                         ^
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/stl_pair.h:391:3:
> > > note: in instantiation of template class
> > > 'std::__and_<std::is_copy_assignable<boost::spirit::info>,
> > > std::is_copy_assignable<boost::spirit::info>>' requested here
> > >                __and_<is_copy_assignable<_T1>,
> > >                ^
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/iterator_concepts.h:949:29:
> > > note: in instantiation of template class 'std::pair<boost::spirit::info,
> > > boost::spirit::info>' requested here
> > >          { __detail::__decay_copy(begin(__t)) } ->
> > > input_or_output_iterator;
> > >                                   ^
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/iterator_concepts.h:949:6:
> > > note: in instantiation of requirement here
> > >          { __detail::__decay_copy(begin(__t)) } ->
> > > input_or_output_iterator;
> > >            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/iterator_concepts.h:947:5:
> > > note: while substituting template arguments into constraint expression
> > > here
> > >        && requires(_Tp& __t)
> > >           ^~~~~~~~~~~~~~~~~~
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/ranges_base.h:115:7:
> > > note: (skipping 85 contexts in backtrace; use -ftemplate-backtrace-limit=0
> > > to see all)
> > >          || __adl_begin<_Tp>
> > >             ^
> > > /usr/include/boost/mpl/aux_/preprocessed/gcc/and.hpp:50:7: note: in
> > > instantiation of template class 'boost::mpl::aux::and_impl<true,
> > > boost::mpl::not_<boost::is_const<boost::variant<boost::spirit::info::nil_,
> > > std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>>>>,
> > > boost::detail::variant::is_variant_constructible_from<boost::variant<boost::spirit::info::nil_,
> > > std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>> &&,
> > > boost::mpl::l_item<mpl_::long_<5>, boost::spirit::info::nil_,
> > > boost::mpl::l_item<mpl_::long_<4>, std::basic_string<char>,
> > > boost::mpl::l_item<mpl_::long_<3>,
> > > boost::recursive_wrapper<boost::spirit::info>,
> > > boost::mpl::l_item<mpl_::long_<2>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>, boost::mpl::l_item<mpl_::long_<1>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>,
> > > boost::mpl::l_end>>>>>>, mpl_::bool_<true>, mpl_::bool_<true>>' requested
> > > here
> > >    : aux::and_impl<
> > >      ^
> > > /usr/include/boost/core/enable_if.hpp:41:41: note: in instantiation of
> > > template class
> > > 'boost::mpl::and_<boost::is_rvalue_reference<boost::variant<boost::spirit::info::nil_,
> > > std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>> &&>,
> > > boost::mpl::not_<boost::is_const<boost::variant<boost::spirit::info::nil_,
> > > std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>>>>,
> > > boost::detail::variant::is_variant_constructible_from<boost::variant<boost::spirit::info::nil_,
> > > std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>> &&,
> > > boost::mpl::l_item<mpl_::long_<5>, boost::spirit::info::nil_,
> > > boost::mpl::l_item<mpl_::long_<4>, std::basic_string<char>,
> > > boost::mpl::l_item<mpl_::long_<3>,
> > > boost::recursive_wrapper<boost::spirit::info>,
> > > boost::mpl::l_item<mpl_::long_<2>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>, boost::mpl::l_item<mpl_::long_<1>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>,
> > > boost::mpl::l_end>>>>>>>' requested here
> > >  struct enable_if : public enable_if_c<Cond::value, T> {};
> > >                                        ^
> > > /usr/include/boost/variant/variant.hpp:2136:21: note: in instantiation of
> > > template class
> > > 'boost::enable_if<boost::mpl::and_<boost::is_rvalue_reference<boost::variant<boost::spirit::info::nil_,
> > > std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>> &&>,
> > > boost::mpl::not_<boost::is_const<boost::variant<boost::spirit::info::nil_,
> > > std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>>>>,
> > > boost::detail::variant::is_variant_constructible_from<boost::variant<boost::spirit::info::nil_,
> > > std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>> &&,
> > > boost::mpl::l_item<mpl_::long_<5>, boost::spirit::info::nil_,
> > > boost::mpl::l_item<mpl_::long_<4>, std::basic_string<char>,
> > > boost::mpl::l_item<mpl_::long_<3>,
> > > boost::recursive_wrapper<boost::spirit::info>,
> > > boost::mpl::l_item<mpl_::long_<2>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>, boost::mpl::l_item<mpl_::long_<1>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>,
> > > boost::mpl::l_end>>>>>>>, boost::variant<boost::spirit::info::nil_,
> > > std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>> &>' requested
> > > here
> > >    typename boost::enable_if<
> > >                    ^
> > > /usr/include/boost/variant/variant.hpp:1105:7: note: while substituting
> > > deduced template arguments into function template 'operator=' [with T =
> > > boost::variant<boost::spirit::info::nil_, std::basic_string<char>,
> > > boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>>]
> > > class variant
> > >      ^
> > > /usr/include/boost/spirit/home/support/info.hpp:29:12: note: while
> > > declaring the implicit move assignment operator for 'info'
> > >    struct info
> > >           ^
> > > In file included from test.cc:1:
> > > In file included from /usr/include/boost/spirit/include/qi.hpp:16:
> > > In file included from /usr/include/boost/spirit/home/qi.hpp:14:
> > > In file included from /usr/include/boost/spirit/home/qi/action.hpp:14:
> > > In file included from
> > > /usr/include/boost/spirit/home/qi/action/action.hpp:14:
> > > In file included from
> > > /usr/include/boost/spirit/home/qi/meta_compiler.hpp:14:
> > > In file included from
> > > /usr/include/boost/spirit/home/support/meta_compiler.hpp:17:
> > > In file included from
> > > /usr/include/boost/spirit/home/support/make_component.hpp:15:
> > > In file included from
> > > /usr/include/boost/spirit/home/support/detail/make_cons.hpp:16:
> > > In file included from /usr/include/boost/fusion/include/cons.hpp:10:
> > > In file included from /usr/include/boost/fusion/support/config.hpp:13:
> > > In file included from
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/utility:70:
> > > In file included from
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/stl_pair.h:59:
> > > In file included from
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/move.h:57:
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/type_traits:1081:7:
> > > error: static_assert failed due to requirement
> > > 'std::__is_complete_or_unbounded(std::__type_identity<boost::spirit::info>{})'
> > > "template argument must be a complete class or an unbounded array"
> > >      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
> > >      ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/type_traits:139:26:
> > > note: in instantiation of template class
> > > 'std::is_move_assignable<boost::spirit::info>' requested here
> > >    : public conditional<_B1::value, _B2, _B1>::type
> > >                         ^
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/stl_pair.h:402:3:
> > > note: in instantiation of template class
> > > 'std::__and_<std::is_move_assignable<boost::spirit::info>,
> > > std::is_move_assignable<boost::spirit::info>>' requested here
> > >                __and_<is_move_assignable<_T1>,
> > >                ^
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/iterator_concepts.h:949:29:
> > > note: in instantiation of template class 'std::pair<boost::spirit::info,
> > > boost::spirit::info>' requested here
> > >          { __detail::__decay_copy(begin(__t)) } ->
> > > input_or_output_iterator;
> > >                                   ^
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/iterator_concepts.h:949:6:
> > > note: in instantiation of requirement here
> > >          { __detail::__decay_copy(begin(__t)) } ->
> > > input_or_output_iterator;
> > >            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/iterator_concepts.h:947:5:
> > > note: while substituting template arguments into constraint expression
> > > here
> > >        && requires(_Tp& __t)
> > >           ^~~~~~~~~~~~~~~~~~
> > > ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.1/../../../../include/c++/11.0.1/bits/ranges_base.h:115:7:
> > > note: (skipping 85 contexts in backtrace; use -ftemplate-backtrace-limit=0
> > > to see all)
> > >          || __adl_begin<_Tp>
> > >             ^
> > > /usr/include/boost/mpl/aux_/preprocessed/gcc/and.hpp:50:7: note: in
> > > instantiation of template class 'boost::mpl::aux::and_impl<true,
> > > boost::mpl::not_<boost::is_const<boost::variant<boost::spirit::info::nil_,
> > > std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>>>>,
> > > boost::detail::variant::is_variant_constructible_from<boost::variant<boost::spirit::info::nil_,
> > > std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>> &&,
> > > boost::mpl::l_item<mpl_::long_<5>, boost::spirit::info::nil_,
> > > boost::mpl::l_item<mpl_::long_<4>, std::basic_string<char>,
> > > boost::mpl::l_item<mpl_::long_<3>,
> > > boost::recursive_wrapper<boost::spirit::info>,
> > > boost::mpl::l_item<mpl_::long_<2>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>, boost::mpl::l_item<mpl_::long_<1>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>,
> > > boost::mpl::l_end>>>>>>, mpl_::bool_<true>, mpl_::bool_<true>>' requested
> > > here
> > >    : aux::and_impl<
> > >      ^
> > > /usr/include/boost/core/enable_if.hpp:41:41: note: in instantiation of
> > > template class
> > > 'boost::mpl::and_<boost::is_rvalue_reference<boost::variant<boost::spirit::info::nil_,
> > > std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>> &&>,
> > > boost::mpl::not_<boost::is_const<boost::variant<boost::spirit::info::nil_,
> > > std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>>>>,
> > > boost::detail::variant::is_variant_constructible_from<boost::variant<boost::spirit::info::nil_,
> > > std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>> &&,
> > > boost::mpl::l_item<mpl_::long_<5>, boost::spirit::info::nil_,
> > > boost::mpl::l_item<mpl_::long_<4>, std::basic_string<char>,
> > > boost::mpl::l_item<mpl_::long_<3>,
> > > boost::recursive_wrapper<boost::spirit::info>,
> > > boost::mpl::l_item<mpl_::long_<2>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>, boost::mpl::l_item<mpl_::long_<1>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>,
> > > boost::mpl::l_end>>>>>>>' requested here
> > >  struct enable_if : public enable_if_c<Cond::value, T> {};
> > >                                        ^
> > > /usr/include/boost/variant/variant.hpp:2136:21: note: in instantiation of
> > > template class
> > > 'boost::enable_if<boost::mpl::and_<boost::is_rvalue_reference<boost::variant<boost::spirit::info::nil_,
> > > std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>> &&>,
> > > boost::mpl::not_<boost::is_const<boost::variant<boost::spirit::info::nil_,
> > > std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>>>>,
> > > boost::detail::variant::is_variant_constructible_from<boost::variant<boost::spirit::info::nil_,
> > > std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>> &&,
> > > boost::mpl::l_item<mpl_::long_<5>, boost::spirit::info::nil_,
> > > boost::mpl::l_item<mpl_::long_<4>, std::basic_string<char>,
> > > boost::mpl::l_item<mpl_::long_<3>,
> > > boost::recursive_wrapper<boost::spirit::info>,
> > > boost::mpl::l_item<mpl_::long_<2>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>, boost::mpl::l_item<mpl_::long_<1>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>,
> > > boost::mpl::l_end>>>>>>>, boost::variant<boost::spirit::info::nil_,
> > > std::basic_string<char>, boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>> &>' requested
> > > here
> > >    typename boost::enable_if<
> > >                    ^
> > > /usr/include/boost/variant/variant.hpp:1105:7: note: while substituting
> > > deduced template arguments into function template 'operator=' [with T =
> > > boost::variant<boost::spirit::info::nil_, std::basic_string<char>,
> > > boost::recursive_wrapper<boost::spirit::info>,
> > > boost::recursive_wrapper<std::pair<boost::spirit::info,
> > > boost::spirit::info>>,
> > > boost::recursive_wrapper<std::list<boost::spirit::info>>>]
> > > class variant
> > >      ^
> > > /usr/include/boost/spirit/home/support/info.hpp:29:12: note: while
> > > declaring the implicit move assignment operator for 'info'
> > >    struct info
> > >           ^
> > > 4 errors generated.
> 
> 


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-04-27 17:52 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-22 23:16 [committed] libstdc++: Implement string_view range constructor for C++23 Jonathan Wakely
2021-04-27 14:34 ` Stephan Bergmann
2021-04-27 16:31   ` Jonathan Wakely
2021-04-27 16:56     ` Jonathan Wakely
2021-04-27 17:51     ` Patrick Palka

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).