使用多字符分隔符的 C++ 视图 join_with

Lud*_*ert 1 c++ std-ranges c++23

使用 C++23 视图::join_with 时可以使用多字符串作为分隔符吗?

gcc 14 返回错误消息。

#include <format>
#include <stdio.h>
#include <string>
#include <algorithm>
#include <ranges>
using namespace std;

int main(){
    const string a[2]={"6", "7"};
    const string buffer1 = a | views::join_with('\n') | ranges::to<string>(); //OK
    printf("%s", buffer1.c_str());

    const string buffer2 = a | views::join_with(",\n") | ranges::to<string>(); //KO
    printf("%s", buffer2.c_str());
    return 0;
}
Run Code Online (Sandbox Code Playgroud)
prog.cc: In function 'int main()':
prog.cc:13:30: error: no match for 'operator|' (operand types are 'const std::string [2]' {aka 'const std::__cxx11::basic_string<char> [2]'} and 'std::ranges::views::__adaptor::_Partial<std::ranges::views::_JoinWith, const char*>')
   13 |     const string buffer2 = a | views::join_with(",\n") | ranges::to<string>(); //KO
      |                            ~ ^ ~~~~~~~~~~~~~~~~~~~~~~~
      |                            |                   |
      |                            |                   std::ranges::views::__adaptor::_Partial<std::ranges::views::_JoinWith, const char*>
      |                            const std::string [2] {aka const std::__cxx11::basic_string<char> [2]}
In file included from prog.cc:5:
/opt/wandbox/gcc-head/include/c++/14.0.1/ranges:952:5: note: candidate: 'template<class _Self, class _Range>  requires (__is_range_adaptor_closure<_Self>) && (__adaptor_invocable<_Self, _Range>) constexpr auto std::ranges::views::__adaptor::operator|(_Range&&, _Self&&)'
  952 |     operator|(_Range&& __r, _Self&& __self)
      |     ^~~~~~~~
/opt/wandbox/gcc-head/include/c++/14.0.1/ranges:952:5: note:   template argument deduction/substitution failed:
/opt/wandbox/gcc-head/include/c++/14.0.1/ranges:952:5: note: constraints not satisfied
/opt/wandbox/gcc-head/include/c++/14.0.1/ranges: In substitution of 'template<class _Self, class _Range>  requires (__is_range_adaptor_closure<_Self>) && (__adaptor_invocable<_Self, _Range>) constexpr auto std::ranges::views::__adaptor::operator|(_Range&&, _Self&&) [with _Self = std::ranges::views::__adaptor::_Partial<std::ranges::views::_JoinWith, const char*>; _Range = const std::__cxx11::basic_string<char> (&)[2]]':
prog.cc:13:54:   required from here
/opt/wandbox/gcc-head/include/c++/14.0.1/ranges:952:5: note:    13 |     const string buffer2 = a | views::join_with(",\n") | ranges::to<string>(); //KO
/opt/wandbox/gcc-head/include/c++/14.0.1/ranges:952:5: note:       |                                                      ^
/opt/wandbox/gcc-head/include/c++/14.0.1/ranges:911:13:   required for the satisfaction of '__adaptor_invocable<_Self, _Range>' [with _Self = std::ranges::views::__adaptor::_Partial<std::ranges::views::_JoinWith, const char*>; _Range = const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > (&)[2]]
/opt/wandbox/gcc-head/include/c++/14.0.1/ranges:912:9:   in requirements  [with _Adaptor = std::ranges::views::__adaptor::_Partial<std::ranges::views::_JoinWith, const char*>; _Args = {const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > (&)[2]}]
/opt/wandbox/gcc-head/include/c++/14.0.1/ranges:912:44: note: the required expression 'declval<_Adaptor>()((declval<_Args>)()...)' is invalid
  912 |       = requires { std::declval<_Adaptor>()(declval<_Args>()...); };
      |                    ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
cc1plus: note: set '-fconcepts-diagnostics-depth=' to at least 2 for more detail
/opt/wandbox/gcc-head/include/c++/14.0.1/ranges:961:5: note: candidate: 'template<class _Lhs, class _Rhs>  requires (__is_range_adaptor_closure<_Lhs>) && (__is_range_adaptor_closure<_Rhs>) constexpr auto std::ranges::views::__adaptor::operator|(_Lhs&&, _Rhs&&)'
  961 |     operator|(_Lhs&& __lhs, _Rhs&& __rhs)
      |     ^~~~~~~~
/opt/wandbox/gcc-head/include/c++/14.0.1/ranges:961:5: note:   template argument deduction/substitution failed:
/opt/wandbox/gcc-head/include/c++/14.0.1/ranges:961:5: note: constraints not satisfied
/opt/wandbox/gcc-head/include/c++/14.0.1/ranges: In substitution of 'template<class _Lhs, class _Rhs>  requires (__is_range_adaptor_closure<_Lhs>) && (__is_range_adaptor_closure<_Rhs>) constexpr auto std::ranges::views::__adaptor::operator|(_Lhs&&, _Rhs&&) [with _Lhs = const std::__cxx11::basic_string<char> (&)[2]; _Rhs = std::ranges::views::__adaptor::_Partial<std::ranges::views::_JoinWith, const char*>]':
prog.cc:13:54:   required from here
/opt/wandbox/gcc-head/include/c++/14.0.1/ranges:961:5: note:    13 |     const string buffer2 = a | views::join_with(",\n") | ranges::to<string>(); //KO
/opt/wandbox/gcc-head/include/c++/14.0.1/ranges:961:5: note:       |                                                      ^
/opt/wandbox/gcc-head/include/c++/14.0.1/ranges:942:13:   required for the satisfaction of '__is_range_adaptor_closure<_Lhs>' [with _Lhs = const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > (&)[2]]
/opt/wandbox/gcc-head/include/c++/14.0.1/ranges:943:9:   in requirements with '_Tp __t' [with _Tp = const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > (&)[2]]
/opt/wandbox/gcc-head/include/c++/14.0.1/ranges:943:70: note: the required expression 'std::ranges::views::__adaptor::__is_range_adaptor_closure_fn(__t, __t)' is invalid
  943 |       = requires (_Tp __t) { __adaptor::__is_range_adaptor_closure_fn(__t, __t); };
      |                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
In file included from /opt/wandbox/gcc-head/include/c++/14.0.1/format:44,
                 from prog.cc:1:
/opt/wandbox/gcc-head/include/c++/14.0.1/charconv:626:3: note: candidate: 'constexpr std::chars_format std::operator|(chars_format, chars_format)'
  626 |   operator|(chars_format __lhs, chars_format __rhs) noexcept
      |   ^~~~~~~~
/opt/wandbox/gcc-head/include/c++/14.0.1/charconv:626:26: note:   no known conversion for argument 1 from 'const std::string [2]' {aka 'const std::__cxx11::basic_string<char> [2]'} to 'std::chars_format'
  626 |   operator|(chars_format __lhs, chars_format __rhs) noexcept
      |             ~~~~~~~~~~~~~^~~~~
In file included from /opt/wandbox/gcc-head/include/c++/14.0.1/bits/memory_resource.h:38,
                 from /opt/wandbox/gcc-head/include/c++/14.0.1/string:67,
                 from /opt/wandbox/gcc-head/include/c++/14.0.1/bits/locale_classes.h:40,
                 from /opt/wandbox/gcc-head/include/c++/14.0.1/locale:41,
                 from /opt/wandbox/gcc-head/include/c++/14.0.1/format:47:
/opt/wandbox/gcc-head/include/c++/14.0.1/cstddef:136:3: note: candidate: 'constexpr std::byte std::operator|(byte, byte)'
  136 |   operator|(byte __l, byte __r) noexcept
      |   ^~~~~~~~
/opt/wandbox/gcc-head/include/c++/14.0.1/cstddef:136:18: note:   no known conversion for argument 1 from 'const std::string [2]' {aka 'const std::__cxx11::basic_string<char> [2]'} to 'std::byte'
  136 |   operator|(byte __l, byte __r) noexcept
      |             ~~~~~^~~
In file included from /opt/wandbox/gcc-head/include/c++/14.0.1/bits/locale_facets.h:43,
                 from /opt/wandbox/gcc-head/include/c++/14.0.1/locale:42:
/opt/wandbox/gcc-head/include/c++/14.0.1/bits/ios_base.h:87:3: note: candidate: 'constexpr std::_Ios_Fmtflags std::operator|(_Ios_Fmtflags, _Ios_Fmtflags)'
   87 |   operator|(_Ios_Fmtflags __a, _Ios_Fmtflags __b)
      |   ^~~~~~~~
/opt/wandbox/gcc-head/include/c++/14.0.1/bits/ios_base.h:87:27: note:   no known conversion for argument 1 from 'const std::string [2]' {aka 'const std::__cxx11::basic_string<char> [2]'} to 'std::_Ios_Fmtflags'
   87 |   operator|(_Ios_Fmtflags __a, _Ios_Fmtflags __b)
      |             ~~~~~~~~~~~~~~^~~
/opt/wandbox/gcc-head/include/c++/14.0.1/bits/ios_base.h:130:3: note: candidate: 'constexpr std::_Ios_Openmode std::operator|(_Ios_Openmode, _Ios_Openmode)'
  130 |   operator|(_Ios_Openmode __a, _Ios_Openmode __b)
      |   ^~~~~~~~
/opt/wandbox/gcc-head/include/c++/14.0.1/bits/ios_base.h:130:27: note:   no known conversion for argument 1 from 'const std::string [2]' {aka 'const std::__cxx11::basic_string<char> [2]'} to 'std::_Ios_Openmode'
  130 |   operator|(_Ios_Openmode __a, _Ios_Openmode __b)
      |             ~~~~~~~~~~~~~~^~~
/opt/wandbox/gcc-head/include/c++/14.0.1/bits/ios_base.h:170:3: note: candidate: 'constexpr std::_Ios_Iostate std::operator|(_Ios_Iostate, _Ios_Iostate)'
  170 |   operator|(_Ios_Iostate __a, _Ios_Iostate __b)
      |   ^~~~~~~~
/opt/wandbox/gcc-head/include/c++/14.0.1/bits/ios_base.h:170:26: note:   no known conversion for argument 1 from 'const std::string [2]' {aka 'const std::__cxx11::basic_string<char> [2]'} to 'std::_Ios_Iostate'
  170 |   operator|(_Ios_Iostate __a, _Ios_Iostate __b)
      |             ~~~~~~~~~~~~~^~~
Run Code Online (Sandbox Code Playgroud)

0xb*_*ann 5

"..."是类型const char*,但join_with要求连接的模式是一个ranges::forward_range或单个对象(cppreference)。您可以使用std::literals轻松地将 转换"..."std::strings 或std::string_viewss:

using namespace std::literals;
const std::string a[2]={"6", "7"};

auto buffer1 = a | std::views::join_with('\n') | std::ranges::to<std::string>(); //OK

auto buffer2 = a | std::views::join_with(",\n"s) | std::ranges::to<std::string>(); //OK

auto buffer3 = a | std::views::join_with(",\n"sv) | std::ranges::to<std::string>(); //OK
Run Code Online (Sandbox Code Playgroud)

查看演示