Some legacy code looks like:
#include <boost/array.hpp>
boost::array<wchar_t, 1000> data;
void func(std::wstring &str)
{
str.assign(data.begin());
}
I am updating code to use std equivalents to boost as we update to C++17, and I thought array was a direct replacement, but when I try this I get a compile error:
#include <array>
std::array<wchar_t, 1000> data;
void func(std::wstring &str)
{
str.assign(data.begin());
}
error C2664: 'std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t>> &std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t>>::assign(std::initializer_list<_Elem>)': cannot convert argument 1 from 'std::_Array_iterator<_Ty,2001>' to 'std::initializer_list<_Elem>' with [ _Elem=wchar_t ] and [ _Ty=wchar_t ] and [ _Elem=wchar_t ]
We use this pattern in quite a lot of places in our codebase, is there a trivial fix? What specifically is the difference between boost::array and std::array which causes this, and does this mean it cannot be considered a drop-in replacement?
(I didn't write this code. And I don't know why we aren't just using wchar_t[]; maybe the author just liked the 'new' features in boost.)
boost::array<wchar_t, N>::iteratoris defined as anwchar_t *std::array<wchar_t, N>::iteratoris not required to be awchar_t *.That's why your code fails to compile. It assumes that the iterators are pointers.
Besides that, the code you have is problematic because
str.assign(_pointer_)assumes that the pointer points to a null-terminated string.However, the good news is that
str.assign(data.begin(), data.end())will work forboost::arrayandstd::arrayboth.However, if you have a NUL in the middle of the array, then you'll get different behavior than you did before. This will give you the same behavior as before:
str.assign(data.begin(), std::find(data.begin(), data.end(), wchar_t(0)))[Later: Well, except in the case where
datadid not contain a NUL. In that case, you had undefined behavior before, but now you get all the elements in the array (and only those). ]