This question has been answered before by using ranges, but I'm using C 17 with a backport of std::span
- so I have spans but not ranges.
Consider this simple function:
std::span<std::string_view> cmdline_args_to_span(int argc, const char* argv[])
{
return std::span<const char*>(argv, argc);
}
I thought the converting constructor of span
would kick in due to the const char*
constructor of std::string_view
but it isn't. And neither is:
std::span<std::string_view> cmdline_args_to_span(int argc, const char* argv[])
{
auto c_args = std::span<const char*>(argv, argc);
return std::span<std::string_view>(c_args);
}
Or:
std::span<std::string_view> cmdline_args_to_span(int argc, const char* argv[])
{
auto c_args = std::span<const char*>(argv, argc);
return std::span<std::string_view>(c_args.begin(), c_args.end());
}
All of these fail on both Clang and gcc (using the 'real' std::span
but it's the same for my backported version).
I must be doing something stupid, but I can't see what - can anyone help?
CodePudding user response:
Convert main args to `spanstd::string_view without ranges
This question has been answered before
You'll notice that the "answered before" solution doesn't create a std::span<std::string_view>
at all.
std::span
is not an adapter range whose iterators would generate objects upon indirection such as std::views::transform
is and does. You cannot have a std::span<std::string_view>
unless you have an array of std::string_view
objects. And those objects won't be stored within the span.
std::span<std::string_view>
isn't very convenient for command line arguments. But, you could first create a std::vector<std::string_view>
and then a span pointing to the vector. Since command line arguments are global, this is a rare case where a static storage doesn't suffer from significant problems - unless the caller mistakenly thinks that they can call it with varying arguments:
std::span<std::string_view>
cmdline_args_to_span(int argc, const char* argv[])
{
static std::vector<std::string_view> args(argv, argv argc);
return args;
}
but I'm using C 17 with a backport of std::span - so I have spans but not ranges.
Ranges can be had pre-C 20 even though the standard library doesn't have them. In fact, the standard ranges are based on a library that works in C 14.
That said, in case you aren't interested in using any of the pre-existing range libraries, then implementing a transform view yourself involves quite a bit of boilerplate.