是否在 c++23 中向 std::string 添加了接受 std::array<char, N> 的新构造函数?

Gra*_*esa 5 c++ c++23

最近在我们的代码中发现了一个错误,我们不小心将 a 转换std::array<char, N>std::string. 有缺陷的代码不会在 c++20 模式下编译,但会在 c++23 模式下编译并 //mostly// 工作,除了一些带有 null 终止的边缘情况。我正在使用海湾合作委员会11.1。

#include <iostream>
#include <string>
#include <array>

int main()
{
    std::array<char, 3> x = {'a', 'b', '\0'};
    std::string s(x);
    std::cout << "'" << s << "'" << " has length " << s.size() << std::endl;
    //outputs "'ab' has length 3"
}
Run Code Online (Sandbox Code Playgroud)

我怀疑这可能与P1989R2 - std::basic_string_view 的范围构造函数有关,但我不知道该怎么做。

这是一个错误还是只是一个奇怪的行为还是什么?

Bar*_*rry 10

是的,和P1989有关。

std::string构造函数之一是:

template< class StringViewLike >
explicit constexpr basic_string( const StringViewLike& t,
                                 const Allocator& alloc = Allocator() );
Run Code Online (Sandbox Code Playgroud)

其受限于StringViewLike可转换为std::string_view.

P1989 将此构造函数添加到std::string_view

template <class R> requires /* ... */
constexpr string_view(R&&);
Run Code Online (Sandbox Code Playgroud)

那里的约束需要R具有contiguous_range适当的值类型和其他一些东西。重要的是,std::array<char, N>满足这些要求,而这个构造函数不是explicit

因此,您现在可以std::string从 a构造 a std::array<char, N>

这导致了P2499string_view范围构造函数应该是explicit),它建议标题所说的内容,以及P2516string_view可以从什么隐式转换?),它建议完全删除构造函数。最后,决定创建构造函数 explicit而不是完全删除它(或保持隐式):

template< class R >
explicit constexpr basic_string_view( R&& r );
Run Code Online (Sandbox Code Playgroud)

因为string构造函数 fromStringViewLike被限制为可转换为(需要隐式构造),所以该方法std::string不再可以从std::array<char, N>(or std::vector<char>or ... ) 构造。

  • @GranBurguesa 明确地说,是的。从 `std::array&lt;char, 3&gt;{'a', 'b', '\0'}` 构造将会得到一个长度为 3 而不是 2 的 `std::string_view`。 (3认同)