string

Modifiable sequences of characters are represented using objects of type string.

The interface and functionality of string is the same as std::string except that:

  • string is not a class template,

  • string uses char as its character type,

  • redundant overloads for string operations have been replaced with a string_view-based interface,

  • access to characters in the range [size(), capacity()) is permitted,

  • storage_ptr is used instead of Allocator, and

  • small buffer optimisation is guaranteed, which avoids allocating memory for small strings.

With augmented interface, operations requiring an input string are implemented as a single overload with a parameter of type string_view, and can accept most string-like objects. Objects such as null terminated character pointers, std::string, string, subranges of strings, and objects convertible to string_view can all be passed to these functions.

json::string str = "Boost.JSON";
json::string_view sv = str;

// all of these call compare(string_view)
str.compare(sv);

str.compare(sv.substr(0, 5));

str.compare(str);

str.compare("Boost");

More formally, std::string member function overloads that accept any of the following parameter combinations as an input string:

  • a std::string parameter, or

  • a std::string parameter and two size_type parameters that specify a substring, or

  • a parameter of a type convertible to string_view, or

  • a parameter of a type convertible to string_view and two size_type parameters that specify a substring, or

  • a const_pointer parameter, or

  • a parameter of type const_pointer and a size_type parameter that specifies the length of the string

are replaced with an overload accepting a string_view parameter.

This design removes several redundant overloads from the interface. For example, the 11 overloads of std::string::insert are reduced to just 3 in string, while still providing identical functionality. In addition to these changes, overloads taking a std::initializer_list<char> parameter have been removed. Such overloads have little use, as they serve as little more than wrappers for arrays with an inefficient syntax:

std::string sstr = "hello";

json::string jstr = "hello";

assert(sstr.append({'w', 'o', 'r', 'l', 'd'}) == "helloworld");

// such syntax is inefficient, and the same can
// be achieved with a character array.

assert(jstr.append("world") == "helloworld");

With the removal of overloads that specify parameters for a substring, a member function subview that returns a string_view is provided to facilitate cheap substring operations:

std::string sstr1 = "helloworld";
std::string sstr2 = "world";

json::string jstr1 = "helloworld";
json::string jstr2 = "world";

assert( jstr2.insert(0, jstr1.subview(0, 5)) == "helloworld" );

// this is equivalent to
assert( sstr2.insert(0, sstr1, 0, 5) == "helloworld" );

A string may be constructed using the default memory resource without incurring any memory allocations. Alternatively, a storage_ptr can be provided explicitly:

string str1; // empty string, uses the default memory resource

string str2( make_shared_resource<monotonic_resource>() ); // empty string, uses a counted monotonic resource

Formatted Output

When a string is formatted to a std::ostream, the result is a valid JSON. That is, the result will be double quoted and the contents properly escaped per the JSON specification.

Accessing Storage Beyond size()

string directly supports access to its storage in the range [size(), capacity()). This can be used for efficient assembly of a string from several parts. After the string is assembled, use the member function string::grow to update the string’s size and insert the null terminator. For example:

string greeting( string_view first_name, string_view last_name )
{
    const char hello[] = "Hello, ";
    const std::size_t sz = first_name.size() + last_name.size() + sizeof(hello) + 1;

    string js;
    js.reserve(sz);

    char* p = std::copy( hello, hello + sizeof(hello) - 1, js.data() );
    p = std::copy( first_name.begin(), first_name.end(), p );
    *p++ = ' ';
    p = std::copy( last_name.begin(), last_name.end(), p );
    *p++ = '!';

    js.grow( sz );
    return js;
}