使用来自 boost::array 与 std::array 的 std::string::assign 不兼容

Posted

技术标签:

【中文标题】使用来自 boost::array 与 std::array 的 std::string::assign 不兼容【英文标题】:Incompatibility using std::string::assign from boost::array Vs std::array 【发布时间】:2021-08-12 14:59:41 【问题描述】:

一些遗留代码如下所示:

#include <boost/array.hpp>

boost::array<wchar_t, 1000> data;

void func(std::wstring &str)

 str.assign(data.begin());

当我们更新到 C++17 时,我正在更新代码以使用 boost 等效的 boost,我认为 array 是直接替代品,但是当我尝试这个时,我得到一个编译错误:

#include <array>

std::array<wchar_t, 1000> data;

void func(std::wstring &str)

 str.assign(data.begin());

错误 C2664: 'std::basic_string,std::allocator> &std::basic_string,std::allocator>::assign(std::initializer_list<_elem>)': 无法将参数 1 从 'std::_Array_iterator<_ty>' 转换为 'std::initializer_list<_elem>' 和 [ _Elem=wchar_t ] 和 [ _Ty=wchar_t ] 和 [ _Elem=wchar_t ]

我们在代码库中的很多地方都使用了这种模式,有什么简单的解决方法吗? boost::arraystd::array 之间的具体区别是什么导致了这种情况,这是否意味着它不能被视为直接替代品?

(这段代码不是我写的。我不知道为什么我们不只是使用wchar_t[];也许作者只是喜欢boost中的“新”功能。)

【问题讨论】:

str.assign(data.begin(), data.end()) 有效吗?否则,如果您确定 data 将被空终止,您可能只需要像 str.assign(data.data()) 这样的数组/指针,而不是传递一个迭代器 boost::array::begin 很可能返回一个指针。这是迭代器的有效实现。坦率地说,作者似乎在滥用实现细节。 @CoryKramer 编译确保它工作可能需要更长的时间;)这看起来确实好多了,我想知道 boost 的迭代器有何不同? 【参考方案1】:

boost::array&lt;wchar_t, N&gt;::iterator 被定义为wchar_t *

std::array&lt;wchar_t, N&gt;::iterator 不需要是wchar_t *

这就是您的代码无法编译的原因。它假定迭代器是指针。

除此之外,您的代码存在问题,因为str.assign(_pointer_) 假定指针指向一个以空字符结尾的字符串。

不过,好消息是str.assign(data.begin(), data.end()) 将适用于boost::arraystd::array

但是,如果您在数组中间有一个 NUL,那么您将获得与以前不同的行为。这将为您提供与以前相同的行为:

str.assign(data.begin(), std::find(data.begin(), data.end(), wchar_t(0)))

[稍后:嗯,除了data 不包含 NUL 的情况。在这种情况下,您之前有未定义的行为,但现在您获得了数组中的所有元素(并且只有那些元素)。 ]

【讨论】:

这种用法似乎纯粹是一个字符缓冲区来接收来自 ODBC 调用的结果,传统上你会看到 WCHAR[MAX_LEN] 所以我得到的印象是有人在 10 多年前读过关于 boost 数组的内容,并且想使用它们。

以上是关于使用来自 boost::array 与 std::array 的 std::string::assign 不兼容的主要内容,如果未能解决你的问题,请参考以下文章

清除 boost::array

有没有简单的方法来动态增加 boost::multi_array 维度?

从 std::array 等获取 size_type 的惯用方法

C++ 静态多数组包装器

boost-容器

如何将原始数据附加到 boost::shared_array<char>?