Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Was a new constructor added to std::string in c++23 that accepts std::array<char, N>?

Tags:

c++

c++23

Recently a bug was discovered in our code where we were accidentally converting a std::array<char, N> to std::string. The buggy code doesn't compile in c++20 mode but compiles and //mostly// works in c++23 mode except for some edge cases with null termination. I'm using gcc 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"
}

I suspect this may be related to P1989R2 - Range constructor for std::basic_string_view but I don't know what to make of it.

Is it a bug or just a weird behavior or what?

like image 785
GranBurguesa Avatar asked Sep 07 '26 13:09

GranBurguesa


1 Answers

Yes, it is related to P1989.

One of std::string's constructors is:

template< class StringViewLike >
explicit constexpr basic_string( const StringViewLike& t,
                                 const Allocator& alloc = Allocator() );

which is constrained on StringViewLike being convertible to std::string_view.

P1989 added this constructor to std::string_view:

template <class R> requires /* ... */
constexpr string_view(R&&);

The constraints there require R to be a contiguous_range with appropriate value type and a few other things. Importantly, std::array<char, N> meets those requirements, and this constructor is not explicit.

As a result, you can now construct a std::string from a std::array<char, N>.

This led to P2499 (string_view range constructor should be explicit), which suggested what the title says, and P2516 (string_view is implicitly convertible from what?), which suggested removing the constructor entirely. In the end, the decision was to make the constructor explicit rather than removing it entirely (or keeping it implicit):

template< class R >
explicit constexpr basic_string_view( R&& r );

Because the string constructor from StringViewLike is constrained on convertible to (which requires implicit construction), this means std::string is no longer constructible from std::array<char, N> (or std::vector<char> or ... ).

like image 52
Barry Avatar answered Sep 10 '26 04:09

Barry



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!