最近在我们的代码中发现了一个错误,我们不小心将 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>。
这导致了P2499(string_view范围构造函数应该是explicit),它建议标题所说的内容,以及P2516(string_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 ... ) 构造。