Skip to content
Alex Qzminsky edited this page Jun 7, 2020 · 7 revisions

Views

Views are special span objects which provides non-owning, iterable range over a substring or an entire string. The class string doesn't have the substr(...) method, such as STL's, but similar functionality is available using views and the methods called chars(...):

utf::string Line{ "The more we study — the more we know" };

// This is what actually happens when we use std::cout << Line
std::cout << Line.chars();

// Prints the word "study" — it starts from 12th character index and has length 5
std::cout << Line.chars(12, 5);

If we call the chars(offset, N) method — i.e., its parameterized version — it's good to know that length of a taking range is defined as utf::string::npos by default. This is the special constant with the context-dependent semantics. In this case it defines a range "to the end of the string":

utf::string Line{ "The more we know — the more we forget" };

// Prints "we forget"
std::cout << Line.chars(28);

Views are used in the most unexpected places inside the entire library. For example, when erasing or inserting.

The reason is iterators. We will speak about them later, in the corresponding chapter; now it’s worth mentioning only that iterators are a special class of "pointers". They are a bit unusual than classic STL's iterators, 'cause every iterator must know its "parent" view object. The reason is the customizable direction of the views.

We can change the direction for many operations on an object using the reverse() method:

utf::string Palin{ "Madam, I'm Adam" };
Palin.remove_if(isspace).remove_if(ispunct).to_ascii_lower();

// strings and views are comparable between each other
assert(Palin == Palin.chars().reverse());

Note that reverse() just flips the direction relative to current. If you want to specify it, use the forward() and backward() methods instead.

...as result

To construct a view over specified string, we can use following methods:

  • View over entire string — chars()

This method uses pre-known range and constructs over beginning and ending pointers, so, has constant time complexity. This is the simplest way to make possible to "look inside" the string's content from another function or program module w/o its copying:

auto let_me_have_a_look(utf::string_view eye) -> void
{
    std::cout << eye;    // printing the content of the original string
}

auto foo() -> void
{
    utf::string Line{ "The more we forget — the less we know" };

    let_me_have_a_look(Line.chars());
        /* or */
    let_me_have_a_look(Line);    // it works too!
}
  • View over the substring — chars(offset, N), right(N), left(N), truncate(offset, N)

If we want to restrict view's range to the specified limit, the library provides us several ways to do this. First, there is the parameterized version of the chars() method (see above). Second, to work with the view representing several first or last characters of the string, we can respectively use the special functions: first(N) and last(N), where N is a count of UTF-8 characters from specified side.

Parameterized chars(offset, N) — this is just a wrapper over the construction chars().truncate(offset, N). The method truncate() applies to the view and does all the work in reality.

  • Search — find() methods

The search methods parameterizing with only a substring (presented via another view) returns a view of the first occurence or an std::vector of all of occurences. For example:

utf::string Line{ "The less we know — the less we forget" };
//                     ↑                  ↑
//                    (1)                (2)

std::cout << Line.chars().find("less");      // prints "less" as it found at (1)
std::cout << Line.chars(10).find("less");    // prints "less" as it found at (2)

auto all = Line.chars().matches("less");     // { "less", "less" }

...as parameters

Besides the search, views may be the input parameters for other string methods.

  • Remove all occurences of the substring — remove(view)

  • Delete characters in the specified range — erase(view)

Note that difference between these methods is their operating principles. The remove() method searches for the given sample (which could be the string or the Unicode character) and deletes every occurence. The method erase() performs a single deletion of characters in range.

  • Checking an occurence of the substring — contains(view)

This is the predicate which only checks if the substring is present in the string or the view.

Clone this wiki locally