Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

This is the documentation for an old version of Boost. Click here to view this page for the latest version.
PrevUpHomeNext

String View

Introduction
Examples
Synopsis
History
Reference
Acknowledgments

The class boost::string_view and other classes derived from basic_string_view represent references to strings or substrings. 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. Before std::string_view, the canonical way to do this used to be 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) If 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.

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

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

boost::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 do not need to change the underlying data. For example, std::sort and std::remove will not work.

Besides generic container functionality, boost::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, boost::string_view has a static member variable named npos to denote the result of failed searches, and to mean "the end".

[Caution] Caution

Because a boost::string_view does not own the data that it refers 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] Note

Boost.Utility also includes the class string_ref:

- string_ref is the initial implementation of Jeffrey Yaskin's N3442: string_ref: a non-owning reference to a string.

- string_view is an updated implementation to reflect the Library Fundamentals TS N4480: [string.view].

Please prefer string_view / basic_string_view over string_ref / basic_string_ref:

- The basic_string_view class better matches std::basic_string_view.

- basic_string_view has WAY more constexpr support.

- Code that uses basic_string_ref should continue to work.

- Not much code depends on basic_string_ref anymore.

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::string s are created, and two copy operations. That is 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_view s created, and two string_view s copied, but those are cheap operations.

The header file <boost/utility/string_view.hpp> defines a template boost::basic_string_view, and four specializations string_view, wstring_view, u16string_view, u32string_view - for char / wchar_t / char16_t / char32_t.

#include <boost/utility/string_view.hpp>

Construction and copying:

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

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

Basic container-like functions:

constexpr size_type size()     const ;
constexpr size_type length()   const ;
constexpr size_type max_size() const ;
constexpr bool empty()         const ;

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

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

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

Modifying the string_view (but not the underlying data):

void clear();
void remove_prefix(size_type n);
void remove_suffix(size_type n);

Searching:

size_type find(basic_string_view s) const ;
size_type find(charT c) const ;
size_type rfind(basic_string_view s) const ;
size_type rfind(charT c) const ;
size_type find_first_of(charT c) const ;
size_type find_last_of (charT c) const ;

size_type find_first_of(basic_string_view s) const ;
size_type find_last_of(basic_string_view s) const ;
size_type find_first_not_of(basic_string_view s) const ;
size_type find_first_not_of(charT c) const ;
size_type find_last_not_of(basic_string_view s) const ;
size_type find_last_not_of(charT c) const ;

String-like operations:

constexpr basic_string_view substr(size_type pos, size_type n=npos) const ; // Creates a new string_view
bool starts_with(charT c) const ;
bool starts_with(basic_string_view x) const ;
bool ends_with(charT c) const ;
bool ends_with(basic_string_view x) const ;
boost 1.71
  • Glen Fernandes updated the implementation of the stream insertion operator to write directly to the basic_streambuf and refactored that functionality into a common utility.
boost 1.53
  • Introduced

Reference

namespace boost {
  template<typename charT, typename traits> class basic_string_view;
  template<typename charT, typename traits> 
    constexpr bool 
    operator==(basic_string_view< charT, traits > x, 
               basic_string_view< charT, traits > y);
  template<typename charT, typename traits> 
    constexpr bool 
    operator!=(basic_string_view< charT, traits > x, 
               basic_string_view< charT, traits > y);
  template<typename charT, typename traits> 
    constexpr bool 
    operator<(basic_string_view< charT, traits > x, 
              basic_string_view< charT, traits > y);
  template<typename charT, typename traits> 
    constexpr bool 
    operator>(basic_string_view< charT, traits > x, 
              basic_string_view< charT, traits > y);
  template<typename charT, typename traits> 
    constexpr bool 
    operator<=(basic_string_view< charT, traits > x, 
               basic_string_view< charT, traits > y);
  template<typename charT, typename traits> 
    constexpr bool 
    operator>=(basic_string_view< charT, traits > x, 
               basic_string_view< charT, traits > y);
  template<typename charT, typename traits, typename Allocator> 
    constexpr bool 
    operator==(basic_string_view< charT, traits > x, 
               const std::basic_string< charT, traits, Allocator > & y);
  template<typename charT, typename traits, typename Allocator> 
    constexpr bool 
    operator==(const std::basic_string< charT, traits, Allocator > & x, 
               basic_string_view< charT, traits > y);
  template<typename charT, typename traits> 
    constexpr bool 
    operator==(basic_string_view< charT, traits > x, const charT * y);
  template<typename charT, typename traits> 
    constexpr bool 
    operator==(const charT * x, basic_string_view< charT, traits > y);
  template<typename charT, typename traits, typename Allocator> 
    constexpr bool 
    operator!=(basic_string_view< charT, traits > x, 
               const std::basic_string< charT, traits, Allocator > & y);
  template<typename charT, typename traits, typename Allocator> 
    constexpr bool 
    operator!=(const std::basic_string< charT, traits, Allocator > & x, 
               basic_string_view< charT, traits > y);
  template<typename charT, typename traits> 
    constexpr bool 
    operator!=(basic_string_view< charT, traits > x, const charT * y);
  template<typename charT, typename traits> 
    constexpr bool 
    operator!=(const charT * x, basic_string_view< charT, traits > y);
  template<typename charT, typename traits, typename Allocator> 
    constexpr bool 
    operator<(basic_string_view< charT, traits > x, 
              const std::basic_string< charT, traits, Allocator > & y);
  template<typename charT, typename traits, typename Allocator> 
    constexpr bool 
    operator<(const std::basic_string< charT, traits, Allocator > & x, 
              basic_string_view< charT, traits > y);
  template<typename charT, typename traits> 
    constexpr bool 
    operator<(basic_string_view< charT, traits > x, const charT * y);
  template<typename charT, typename traits> 
    constexpr bool 
    operator<(const charT * x, basic_string_view< charT, traits > y);
  template<typename charT, typename traits, typename Allocator> 
    constexpr bool 
    operator>(basic_string_view< charT, traits > x, 
              const std::basic_string< charT, traits, Allocator > & y);
  template<typename charT, typename traits, typename Allocator> 
    constexpr bool 
    operator>(const std::basic_string< charT, traits, Allocator > & x, 
              basic_string_view< charT, traits > y);
  template<typename charT, typename traits> 
    constexpr bool 
    operator>(basic_string_view< charT, traits > x, const charT * y);
  template<typename charT, typename traits> 
    constexpr bool 
    operator>(const charT * x, basic_string_view< charT, traits > y);
  template<typename charT, typename traits, typename Allocator> 
    constexpr bool 
    operator<=(basic_string_view< charT, traits > x, 
               const std::basic_string< charT, traits, Allocator > & y);
  template<typename charT, typename traits, typename Allocator> 
    constexpr bool 
    operator<=(const std::basic_string< charT, traits, Allocator > & x, 
               basic_string_view< charT, traits > y);
  template<typename charT, typename traits> 
    constexpr bool 
    operator<=(basic_string_view< charT, traits > x, const charT * y);
  template<typename charT, typename traits> 
    constexpr bool 
    operator<=(const charT * x, basic_string_view< charT, traits > y);
  template<typename charT, typename traits, typename Allocator> 
    constexpr bool 
    operator>=(basic_string_view< charT, traits > x, 
               const std::basic_string< charT, traits, Allocator > & y);
  template<typename charT, typename traits, typename Allocator> 
    constexpr bool 
    operator>=(const std::basic_string< charT, traits, Allocator > & x, 
               basic_string_view< charT, traits > y);
  template<typename charT, typename traits> 
    constexpr bool 
    operator>=(basic_string_view< charT, traits > x, const charT * y);
  template<typename charT, typename traits> 
    constexpr bool 
    operator>=(const charT * x, basic_string_view< charT, traits > y);
  template<typename charT, typename traits> 
    std::basic_ostream< charT, traits > & 
    operator<<(std::basic_ostream< charT, traits > & os, 
               const basic_string_view< charT, traits > & str);
  template<typename It> std::size_t hash_range(It, It);
  template<typename charT, typename traits> 
    std::size_t hash_value(basic_string_view< charT, traits > s);
}

Author: Clow, Marshall

Copyright 2012 Marshall Clow


PrevUpHomeNext