Boost C++ Libraries Home Libraries People FAQ More

String_View

Marshall Clow

Beman Dawes

Distributed under the Boost Software License, Version 1.0. http://www.boost.org/LICENSE_1_0.txt


Table of Contents

Overview
Examples
Reference
Compiler Support
History

Boost.StringView is an implementation of string_view as specified in N4480: ISO/IEC DTS 19568, Technical Specification - C++ Extensions for Library Fundamentals.

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 std::string, but that has certain drawbacks:

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.

2) if a routine receives a constant std::string and wants to pass a portion of that string to another routine, then it must create a new string of that substring.

3) A routine receives a constant std::string and wants to return a portion of the string, then it must create a new string to return.

string_view is designed to solve these efficiency problems. A string_view is a read-only reference to a contiguous sequence of characters, and provides much of the functionality of std::string. A string_view is cheap to create, copy and pass by value, because it does not actually own the storage that it points to.

A string_view is implemented as a small struct that contains a pointer to the start of the character data and a count. A string_view is cheap to create and cheap to copy.

string_view acts as a container; it includes all the methods that you would expect in a container, including iteration support, operator [], at and size. It can be used with any of the iterator-based algorithms in the STL - as long as you don't need to change the underlying data (sort and remove, for example, will not work)

Besides generic container functionality, string_view provides a subset of the interface of std::string. This makes it easy to replace parameters of type const std::string & with boost::string_view. Like std::string, string_view has a static member variable named npos to denote the result of failed searches, and to mean "the end".

Because a string_view 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 string_view refers to exists as long as the string_view does.

Note: The header actually contains a class template, basic_string_view and four typedefs:

template<class charT, class traits = char_traits<charT>>
    class basic_string_view;

typedef basic_string_view<char>     string_view;
typedef basic_string_view<char16_t> u16string_view;
typedef basic_string_view<char32_t> u32string_view;
typedef basic_string_view<wchar_t>  wstring_view;

So you can have views of strings of any of the four built-in character types as well as strings of user-defined character-like type strings. For the sake of simple exposition, we concentrate on string_view (i.e. char strings) in this documentation.

Integrating string_view into your code is fairly simple. Wherever you pass a const std::string & or std::string as a parameter, that's a candidate for passing a boost::string_view.

std::string extract_part ( const std::string &bar ) {
    return bar.substr ( 2, 3 );
    }

if ( extract_part ( "ABCDEFG" ).front() == 'C' ) { /* do something */ }

Let's figure out what happens in this (contrived) example.

First, a temporary string is created from the string literal "ABCDEFG", and it is passed (by reference) to the routine extract_part. Then a second string is created in the call std::string::substr and returned to extract_part (this copy may be elided by RVO). Then extract_part returns that string back to the caller (again this copy may be elided). The first temporary string is deallocated, and front is called on the second string, and then it is deallocated as well.

Two std::strings are created, and two copy operations. That's (potentially) four memory allocations and deallocations, and the associated copying of data.

Now let's look at the same code with string_view:

boost::string_view extract_part ( boost::string_view bar ) {
    return bar.substr ( 2, 3 );
    }

if ( extract_part ( "ABCDEFG" ).front() == "C" ) { /* do something */ }

No memory allocations. No copying of character data. No changes to the code other than the types. There are two string_views created, and two string_views copied, but those are cheap operations.

The header file "string_view.hpp" defines a class template boost::basic_string_view, and four specializations - for char / wchar_t / char16_t / char32_t .

#include <boost/utility/string_view.hpp>

Types:

typedef traits traits_type;
typedef charT value_type;
typedef charT* pointer;
typedef const charT* const_pointer;
typedef charT& reference;
typedef const charT& const_reference;
typedef const_pointer const_iterator;  // implementation defined
typedef const_iterator iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef const_reverse_iterator reverse_iterator;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
static BOOST_CONSTEXPR_OR_CONST size_type npos = size_type(-1);

Construction and copying:

BOOST_CONSTEXPR basic_string_view () BOOST_NOEXCEPT;    // Constructs empty string_view
BOOST_CONSTEXPR basic_string_view (const basic_string_view &rhs) BOOST_NOEXCEPT;
basic_string_view& operator=(const basic_string_view &rhs) BOOST_NOEXCEPT;
template<typename Allocator>
  basic_string_view(const std::basic_string<charT, traits, Allocator>& str) BOOST_NOEXCEPT; // Ctor from std::string
BOOST_CONSTEXPR basic_string_view(const charT* str); // Ctor from NULL-terminated string
BOOST_CONSTEXPR basic_string_view(const charT* str, size_type len); // Ctor from pointer, length pair

string_view does not define a move constructor or a move-assignment operator because copying a string_view is just as cheap as moving one would be.

Basic container-like functions:

BOOST_CONSTEXPR size_type size()     const BOOST_NOEXCEPT ;
BOOST_CONSTEXPR size_type length()   const BOOST_NOEXCEPT ;
BOOST_CONSTEXPR size_type max_size() const BOOST_NOEXCEPT ;
BOOST_CONSTEXPR bool empty()         const BOOST_NOEXCEPT ;

// All iterators are const_iterators
BOOST_CONSTEXPR const_iterator  begin() const BOOST_NOEXCEPT ;
BOOST_CONSTEXPR const_iterator cbegin() const BOOST_NOEXCEPT ;
BOOST_CONSTEXPR const_iterator    end() const BOOST_NOEXCEPT ;
BOOST_CONSTEXPR const_iterator   cend() const BOOST_NOEXCEPT ;
const_reverse_iterator         rbegin() const BOOST_NOEXCEPT ;
const_reverse_iterator        crbegin() const BOOST_NOEXCEPT ;
const_reverse_iterator           rend() const BOOST_NOEXCEPT ;
const_reverse_iterator          crend() const BOOST_NOEXCEPT ;

Access to the individual elements (all of which are const):

BOOST_CONSTEXPR const charT& operator[](size_type pos) const ;
BOOST_CONSTEXPR const charT& at(size_t pos) const ;
BOOST_CONSTEXPR const charT& front() const ;
BOOST_CONSTEXPR const charT& back()  const ;
BOOST_CONSTEXPR const charT* data()  const BOOST_NOEXCEPT ;

Modifying the string_view (but not the underlying data):

void clear();  // boost extension
BOOST_CXX14_CONSTEXPR void remove_prefix(size_type n);
BOOST_CXX14_CONSTEXPR void remove_suffix(size_type n);
BOOST_CXX14_CONSTEXPR void swap(basic_string_view& s) BOOST_NOEXCEPT;

Searching:

BOOST_CXX14_CONSTEXPR size_type find(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT;
BOOST_CXX14_CONSTEXPR size_type find(charT c, size_type pos = 0) const BOOST_NOEXCEPT;
BOOST_CXX14_CONSTEXPR size_type find(const charT* s, size_type pos, size_type n) const;
BOOST_CXX14_CONSTEXPR size_type find(const charT* s, size_type pos = 0) const;

BOOST_CXX14_CONSTEXPR size_type rfind(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT;
BOOST_CXX14_CONSTEXPR size_type rfind(charT c, size_type pos = npos) const BOOST_NOEXCEPT;
BOOST_CXX14_CONSTEXPR size_type rfind(const charT* s, size_type pos, size_type n) const;
BOOST_CXX14_CONSTEXPR size_type rfind(const charT* s, size_type pos = npos) const;

BOOST_CXX14_CONSTEXPR size_type find_first_of(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT;
BOOST_CXX14_CONSTEXPR size_type find_first_of(charT c, size_type pos = 0) const BOOST_NOEXCEPT;
BOOST_CXX14_CONSTEXPR size_type find_first_of(const charT* s, size_type pos, size_type n) const;
BOOST_CXX14_CONSTEXPR size_type find_first_of(const charT* s, size_type pos = 0) const;

BOOST_CXX14_CONSTEXPR size_type find_last_of(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT;
BOOST_CXX14_CONSTEXPR size_type find_last_of(charT c, size_type pos = npos) const BOOST_NOEXCEPT;
BOOST_CXX14_CONSTEXPR size_type find_last_of(const charT* s, size_type pos, size_type n) const;
BOOST_CXX14_CONSTEXPR size_type find_last_of(const charT* s, size_type pos = npos) const;

BOOST_CXX14_CONSTEXPR size_type find_first_not_of(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT;
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(charT c, size_type pos = 0) const BOOST_NOEXCEPT;
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(const charT* s, size_type pos, size_type n) const;
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(const charT* s, size_type pos = 0) const;

BOOST_CXX14_CONSTEXPR size_type find_last_not_of(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT;
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(charT c, size_type pos = npos) const BOOST_NOEXCEPT;
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(const charT* s, size_type pos, size_type n) const;
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(const charT* s, size_type pos = npos) const;

BOOST_CONSTEXPR bool starts_with(charT c) const ;                 // boost extension
BOOST_CONSTEXPR bool starts_with(basic_string_view x) const ;     // boost extension
BOOST_CONSTEXPR bool ends_with(charT c) const ;                   // boost extension
BOOST_CONSTEXPR bool ends_with(basic_string_view x) const ;       // boost extension

String-like operations:

template<class Allocator>  // Only present if compiler supports C++11 explicit conversion
  explicit operator basic_string<charT, traits, Allocator>() const;

template<class Allocator = allocator<charT> >  // Default only present if compiler supports
  basic_string<charT, traits, Allocator>       //   C++11 default template parameters
    to_string(const Allocator& a = Allocator()) const;

size_type copy(charT* s, size_type n, size_type pos = 0) const;

BOOST_CXX14_CONSTEXPR basic_string_view substr(size_type pos,
  size_type n=npos) const ; // Create new string_view

Comparison:

To be supplied

This Boost implementation only requires a C++03 compliant compiler.

The actual Library Fundamentals specification assumes a C++14 compliant compiler, so a few features are only present if actually supported by the compiler. Boost macros such as BOOST_CONSTEXPR, BOOST_CXX14_CONSTEXPR, and BOOST_NOEXCEPT supply certain features if supported by the compiler.

boost 1.53

boost 1.60

Last revised: July 17, 2015 at 19:19:23 GMT