从一系列字符构造 string_view

Constructing a string_view from a range of chars

虽然 span 可以从范围构造,但 string_view 不能从字符范围构造。

因此,例如,需要以下代码:

// assume chars_span is a span of chars
std::cout << std::string_view(chars_span.data(), chars_span.size());
// or:
std::cout << std::string_view(chars_span.begin(), chars_span.end());

而不是更简单的 range-syntax 不受支持:

std::cout << std::string_view(chars_span);

string_view 没有接受一系列字符的构造函数是否有原因,或者它只是被忽视或认为不够重要?

P1391r3 proposed this, though this was dropped in the version that was eventually adopted for C++20: P1391r4。不幸的是,论文中完全没有掉落的原因(事实上,论文甚至没有提到它被掉落)。

然而,一篇 follow-up 论文 P1989R0 提出了这个问题,如果我们有这样的类型会发生什么(我稍微修改了这个例子):

struct buffer {
    buffer() {};
    char const* begin() const { return data; }
    char const* end() const { return data + 42; }
    operator string_view() const {
        return string_view(data, data + 2);
    }
private:
    char data[42];
};

在这里,buffer 可转换为 string_view。但是它转换为 string_view 的方式与 string_view 的范围构造函数执行此操作的方式不同(前者给你两个字符,后者给你 42 个)。据我所知,实际上没有人指出这种类型的存在。

然而,方向是确保这些类型继续正常工作,因此新论文对特定构造函数有一组更复杂的约束。


一个更有趣的例子是这样的:

using ci_string = std::basic_string<char, case_insensitive_traits>;

ci_string value = "Hello";
std::string_view sv = value;

任何一种直接的 range-based 推理都可以将 ci_string 转换为 std::stringci_stringchar 的完美连续范围,没有任何奇怪的转换问题,如之前的 buffer 类型。但是虽然 ci_string 应该可以转换为 basic_string_view<char, case_insensitive_traits>,但我们可能不想避免它被转换为正常的 string_view。这不太可能是有意为之,因此我们需要努力防范。

这个案例比 buffer 案例更能激励我。