Я использую G++ 14.1.0, но также было бы неплохо переключиться (сейчас у меня такое ощущение, что G++ поддерживает больше современных C++, чем CLang).
Я использую std::ranges::views:: разбить там много, а затем преобразовать значения в std::string_view через std::ranges::views::split.
Минимальный пример кода:
Код: Выделить всё
#include
#include
using namespace std::literals::string_view_literals;
int main() {
constexpr std::string_view input = "A,B B,C C,D C,E D,F"sv;
constexpr auto working =
input | std::ranges::views::split(","sv) |
std::ranges::views::transform(
[](const auto input) { return std::string_view(input); });
}
Первое, что я попробовал:
Код: Выделить всё
#include
#include
using namespace std::literals::string_view_literals;
int main() {
constexpr std::string_view input = "A,B B,C C,D C,E D,F"sv;
constexpr auto working =
input | std::ranges::views::split(","sv) |
std::ranges::views::transform(std::string_view::string_view);
}
и:
Код: Выделить всё
#include
#include
using namespace std::literals::string_view_literals;
int main() {
constexpr std::string_view input = "A,B B,C C,D C,E D,F"sv;
constexpr auto working =
input | std::ranges::views::split(","sv) |
std::ranges::views::transform(std::string_view);
}
Третий вариант, который я попробовал:
p>
Код: Выделить всё
#include
#include
#include
using namespace std::literals::string_view_literals;
[[nodiscard]] static constexpr std::string_view to_string_view(const auto input)
requires(std::constructible_from)
{
return std::string_view(input);
}
int main() {
constexpr std::string_view input = "A,B B,C C,D C,E D,F"sv;
constexpr auto test = std::ranges::views::transform(
input | std::ranges::views::split(","sv), to_string_view);
}
Код: Выделить всё
> : In function 'int main()':
> :15:56: error: no match for call to '(const std::ranges::views::_Transform) (std::ranges::split_view, )'
> 15 | constexpr auto test = std::ranges::views::transform(
> | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
>. 16 | input | std::ranges::views::split(","sv), to_string_view);
> | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> In file included from :2:
> /opt/compiler-explorer/gcc-trunk-20240629/include/c++/15.0.0/ranges:2212:9: note: candidate: 'template requires (viewable_range) && (__can_transform_view) constexpr auto std::ranges::views::_Transform::operator()(_Range&&, _Fp&&) const'
> 2212 | operator() [[nodiscard]] (_Range&& __r, _Fp&& __f) const
> | ^~~~~~~~
> /opt/compiler-explorer/gcc-trunk-20240629/include/c++/15.0.0/ranges:2212:9: note: template argument deduction/substitution failed:
> :15:56: note: couldn't deduce template parameter '_Fp'
>. 15 | constexpr auto test = std::ranges::views::transform(
> | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
> 16 | input | std::ranges::views::split(","sv), to_string_view);
> | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> /opt/compiler-explorer/gcc-trunk-20240629/include/c++/15.0.0/ranges:991:9: note: candidate: 'template requires __adaptor_partial_app_viable constexpr auto std::ranges::views::__adaptor::_RangeAdaptor::operator()(_Args&& ...) const [with _Args = {_Args ...}; _Derived = std::ranges::views::_Transform]'
> 991 | operator()(_Args&&... __args) const
> | ^~~~~~~~
> /opt/compiler-explorer/gcc-trunk-20240629/include/c++/15.0.0/ranges:991:9: note: template argument deduction/substitution failed:
> /opt/compiler-explorer/gcc-trunk-20240629/include/c++/15.0.0/ranges:991:9: note: constraints not satisfied
> /opt/compiler-explorer/gcc-trunk-20240629/include/c++/15.0.0/ranges: In substitution of 'template requires __adaptor_partial_app_viable constexpr auto std::ranges::views::__adaptor::_RangeAdaptor::operator()(_Args&& ...) const [with _Args = std::ranges::views::_Transform]':
> :15:56: required from here
> 15 | constexpr auto test = std::ranges::views::transform(
> | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
> 16 | input | std::ranges::views::split(","sv), to_string_view);
> | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> /opt/compiler-explorer/gcc-trunk-20240629/include/c++/15.0.0/ranges:921:13: required for the satisfaction of '__adaptor_partial_app_viable' [with _Derived = std::ranges::views::_Transform; _Args = {}]
> /opt/compiler-explorer/gcc-trunk-20240629/include/c++/15.0.0/ranges:922:28: note: the expression 'sizeof ... (_Args ...) == (_Adaptor::_S_arity) - 1 [with _Args = {}; _Adaptor = std::ranges::views::_Transform]' evaluated to 'false'
> 922 | && (sizeof...(_Args) == _Adaptor::_S_arity - 1)
> | ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
> Compiler returned: 1
Поэтому я попытался напрямую попытаться достичь конечной цели и перенести все преобразование в функцию:
Код: Выделить всё
#include
#include
#include
#include
using namespace std::literals::string_view_literals;
static auto constexpr to_string_transform_view = std::bind_back(
std::ranges::views::transform, [](const auto input)
requires(std::constructible_from)
{ return std::string_view(input); });
int main() {
constexpr std::string_view input = "A,B B,C C,D C,E D,F"sv;
auto constexpr test =
to_string_transform_view(input | std::ranges::views::split(","sv));
}
Кроме того, у меня, окей, только один раз есть эта «уродливая» лямбда функция там для очень простой вещи.
Поскольку мне это нужно и для других вещей, я бы предпочел лучший способ.
Благодаря различным ответам в StackOverflow я увидел это boost дает два варианта:
- :
Код: Выделить всё
boost::value_factory
Код: Выделить всё
#include
#include
#include
#include
#include
using namespace std::literals::string_view_literals;
static auto constexpr to_string_transform_view = std::bind_back(
std::ranges::views::transform, boost::value_factory());
int main() {
constexpr std::string_view input = "A,B B,C C,D C,E D,F"sv;
auto constexpr test =
to_string_transform_view(input | std::ranges::views::split(","sv));
}
Код: Выделить всё
boost::lambda::constructor
Код: Выделить всё
#include
#include
#include
#include
#include
using namespace std::literals::string_view_literals;
static auto constexpr to_string_transform_view = std::bind_back(
std::ranges::views::transform, boost::lambda::constructor());
int main() {
constexpr std::string_view input = "A,B B,C C,D C,E D,F"sv;
auto constexpr test =
to_string_transform_view(input | std::ranges::views::split(","sv));
}
- Существуют ли только две реализации одного и того же объекта?
- Подходит ли один для некоторых случаев лучше, чем другой?
- Есть ли способ обойтись без сторонних библиотек?
Подробнее здесь: https://stackoverflow.com/questions/786 ... -using-std