Search code examples
c++boostc++17visual-c++-2019

Incompatibility using std::string::assign from boost::array Vs std::array


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.)


Solution

  • boost::array<wchar_t, N>::iterator is defined as an wchar_t *

    std::array<wchar_t, N>::iterator is not required to be a wchar_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 for boost::array and std::array both.

    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 data did 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). ]