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
useschar
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 twosize_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 twosize_type
parameters that specify a substring, or -
a
const_pointer
parameter, or -
a parameter of type
const_pointer
and asize_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;
}