Boost.StringRef is an implementation of Jeffrey Yaskin's <ahref="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html"target="_top">N3442:
string_ref: a non-owning reference to a string</a>.
</p>
<p>
When you are parsing/processing strings from some external source, frequently
you want to pass a piece of text to a procedure for specialized processing.
The canonical way to do this is as a <codeclass="computeroutput"><spanclass="identifier">std</span><spanclass="special">::</span><spanclass="identifier">string</span></code>,
but that has certain drawbacks:
</p>
<p>
1) If you are processing a buffer of text (say a HTTP response or the contents
of a file), then you have to create the string from the text you want to pass,
which involves memory allocation and copying of data.
</p>
<p>
2) if a routine receives a constant <codeclass="computeroutput"><spanclass="identifier">std</span><spanclass="special">::</span><spanclass="identifier">string</span></code>
and wants to pass a portion of that string to another routine, then it must
create a new string of that substring.
</p>
<p>
3) A routine receives a constant <codeclass="computeroutput"><spanclass="identifier">std</span><spanclass="special">::</span><spanclass="identifier">string</span></code>
and wants to return a portion of the string, then it must create a new string
to return.
</p>
<p>
<codeclass="computeroutput"><spanclass="identifier">string_ref</span></code> is designed to solve
these efficiency problems. A <codeclass="computeroutput"><spanclass="identifier">string_ref</span></code>
is a read-only reference to a contiguous sequence of characters, and provides
much of the functionality of <codeclass="computeroutput"><spanclass="identifier">std</span><spanclass="special">::</span><spanclass="identifier">string</span></code>.
A <codeclass="computeroutput"><spanclass="identifier">string_ref</span></code> is cheap to create,
copy and pass by value, because it does not actually own the storage that it
points to.
</p>
<p>
A <codeclass="computeroutput"><spanclass="identifier">string_ref</span></code> is implemented
as a small struct that contains a pointer to the start of the character data
and a count. A <codeclass="computeroutput"><spanclass="identifier">string_ref</span></code> is
cheap to create and cheap to copy.
</p>
<p>
<codeclass="computeroutput"><spanclass="identifier">string_ref</span></code> acts as a container;
it includes all the methods that you would expect in a container, including
provides a subset of the interface of <codeclass="computeroutput"><spanclass="identifier">std</span><spanclass="special">::</span><spanclass="identifier">string</span></code>.
This makes it easy to replace parameters of type <codeclass="computeroutput"><spanclass="keyword">const</span>
with <codeclass="computeroutput"><spanclass="identifier">boost</span><spanclass="special">::</span><spanclass="identifier">string_ref</span></code>. Like <codeclass="computeroutput"><spanclass="identifier">std</span><spanclass="special">::</span><spanclass="identifier">string</span></code>,
<codeclass="computeroutput"><spanclass="identifier">string_ref</span></code> has a static member
variable named <codeclass="computeroutput"><spanclass="identifier">npos</span></code> to denote
the result of failed searches, and to mean "the end".
</p>
<p>
Because a <codeclass="computeroutput"><spanclass="identifier">string_ref</span></code> does not
own the data that it "points to", it introduces lifetime issues into
code that uses it. The programmer must ensure that the data that a <codeclass="computeroutput"><spanclass="identifier">string_ref</span></code> refers to exists as long as the
or <codeclass="computeroutput"><spanclass="identifier">std</span><spanclass="special">::</span><spanclass="identifier">string</span></code> as a parameter, that's a candidate
for passing a <codeclass="computeroutput"><spanclass="identifier">boost</span><spanclass="special">::</span><spanclass="identifier">string_ref</span></code>.
<spanclass="keyword">if</span><spanclass="special">(</span><spanclass="identifier">extract_part</span><spanclass="special">(</span><spanclass="string">"ABCDEFG"</span><spanclass="special">).</span><spanclass="identifier">front</span><spanclass="special">()</span><spanclass="special">==</span><spanclass="char">'C'</span><spanclass="special">)</span><spanclass="special">{</span><spanclass="comment">/* do something */</span><spanclass="special">}</span>
Let's figure out what happens in this (contrived) example.
</p>
<p>
First, a temporary string is created from the string literal <codeclass="computeroutput"><spanclass="string">"ABCDEFG"</span></code>, and it is passed (by reference)
to the routine <codeclass="computeroutput"><spanclass="identifier">extract_part</span></code>.
Then a second string is created in the call <codeclass="computeroutput"><spanclass="identifier">std</span><spanclass="special">::</span><spanclass="identifier">string</span><spanclass="special">::</span><spanclass="identifier">substr</span></code>
and returned to <codeclass="computeroutput"><spanclass="identifier">extract_part</span></code>
(this copy may be elided by RVO). Then <codeclass="computeroutput"><spanclass="identifier">extract_part</span></code>
returns that string back to the caller (again this copy may be elided). The
first temporary string is deallocated, and <codeclass="computeroutput"><spanclass="identifier">front</span></code>
is called on the second string, and then it is deallocated as well.
</p>
<p>
Two <codeclass="computeroutput"><spanclass="identifier">std</span><spanclass="special">::</span><spanclass="identifier">string</span></code>s are created, and two copy operations.
That's (potentially) four memory allocations and deallocations, and the associated
copying of data.
</p>
<p>
Now let's look at the same code with <codeclass="computeroutput"><spanclass="identifier">string_ref</span></code>:
<spanclass="keyword">if</span><spanclass="special">(</span><spanclass="identifier">extract_part</span><spanclass="special">(</span><spanclass="string">"ABCDEFG"</span><spanclass="special">).</span><spanclass="identifier">front</span><spanclass="special">()</span><spanclass="special">==</span><spanclass="string">"C"</span><spanclass="special">)</span><spanclass="special">{</span><spanclass="comment">/* do something */</span><spanclass="special">}</span>
</pre>
<p>
No memory allocations. No copying of character data. No changes to the code
other than the types. There are two <codeclass="computeroutput"><spanclass="identifier">string_ref</span></code>s
created, and two <codeclass="computeroutput"><spanclass="identifier">string_ref</span></code>s
The header file "string_ref.hpp" defines a template <codeclass="computeroutput"><spanclass="identifier">boost</span><spanclass="special">::</span><spanclass="identifier">basic_string_ref</span></code>,
and four specializations - for <codeclass="computeroutput"><spanclass="keyword">char</span></code>
<preclass="programlisting"><spanclass="identifier">BOOST_CONSTEXPR</span><spanclass="identifier">basic_string_ref</span><spanclass="special">();</span><spanclass="comment">// Constructs an empty string_ref</span>
<spanclass="identifier">BOOST_CONSTEXPR</span><spanclass="identifier">basic_string_ref</span><spanclass="special">(</span><spanclass="keyword">const</span><spanclass="identifier">charT</span><spanclass="special">*</span><spanclass="identifier">str</span><spanclass="special">);</span><spanclass="comment">// Constructs from a NULL-terminated string</span>
<spanclass="identifier">BOOST_CONSTEXPR</span><spanclass="identifier">basic_string_ref</span><spanclass="special">(</span><spanclass="keyword">const</span><spanclass="identifier">charT</span><spanclass="special">*</span><spanclass="identifier">str</span><spanclass="special">,</span><spanclass="identifier">size_type</span><spanclass="identifier">len</span><spanclass="special">);</span><spanclass="comment">// Constructs from a pointer, length pair</span>
<spanclass="identifier">basic_string_ref</span><spanclass="special">(</span><spanclass="keyword">const</span><spanclass="identifier">std</span><spanclass="special">::</span><spanclass="identifier">basic_string</span><spanclass="special"><</span><spanclass="identifier">charT</span><spanclass="special">,</span><spanclass="identifier">traits</span><spanclass="special">,</span><spanclass="identifier">Allocator</span><spanclass="special">>&</span><spanclass="identifier">str</span><spanclass="special">);</span><spanclass="comment">// Constructs from a std::string</span>
<codeclass="computeroutput"><spanclass="identifier">string_ref</span></code> does not define
a move constructor nor a move-assignment operator because copying a <codeclass="computeroutput"><spanclass="identifier">string_ref</span></code> is just a cheap as moving one.
<preclass="programlisting"><spanclass="identifier">BOOST_CONSTEXPR</span><spanclass="identifier">basic_string_ref</span><spanclass="identifier">substr</span><spanclass="special">(</span><spanclass="identifier">size_type</span><spanclass="identifier">pos</span><spanclass="special">,</span><spanclass="identifier">size_type</span><spanclass="identifier">n</span><spanclass="special">=</span><spanclass="identifier">npos</span><spanclass="special">)</span><spanclass="keyword">const</span><spanclass="special">;</span><spanclass="comment">// Creates a new string_ref</span>