template<class charT, class traits = char_traits<charT>>
class basic_string_view {
public:
  
  using traits_type            = traits;
  using value_type             = charT;
  using pointer                = value_type*;
  using const_pointer          = const value_type*;
  using reference              = value_type&;
  using const_reference        = const value_type&;
  using const_iterator         = implementation-defined; 
  using iterator               = const_iterator;
  using const_reverse_iterator = reverse_iterator<const_iterator>;
  using reverse_iterator       = const_reverse_iterator;
  using size_type              = size_t;
  using difference_type        = ptrdiff_t;
  static constexpr size_type npos = size_type(-1);
  
  constexpr basic_string_view() noexcept;
  constexpr basic_string_view(const basic_string_view&) noexcept = default;
  constexpr basic_string_view& operator=(const basic_string_view&) noexcept = default;
  constexpr basic_string_view(const charT* str);
  constexpr basic_string_view(const charT* str, size_type len);
  template<class It, class End>
    constexpr basic_string_view(It begin, End end);
  
  constexpr const_iterator begin() const noexcept;
  constexpr const_iterator end() const noexcept;
  constexpr const_iterator cbegin() const noexcept;
  constexpr const_iterator cend() const noexcept;
  constexpr const_reverse_iterator rbegin() const noexcept;
  constexpr const_reverse_iterator rend() const noexcept;
  constexpr const_reverse_iterator crbegin() const noexcept;
  constexpr const_reverse_iterator crend() const noexcept;
  
  constexpr size_type size() const noexcept;
  constexpr size_type length() const noexcept;
  constexpr size_type max_size() const noexcept;
  [[nodiscard]] constexpr bool empty() const noexcept;
  
  constexpr const_reference operator[](size_type pos) const;
  constexpr const_reference at(size_type pos) const;
  constexpr const_reference front() const;
  constexpr const_reference back() const;
  constexpr const_pointer data() const noexcept;
  
  constexpr void remove_prefix(size_type n);
  constexpr void remove_suffix(size_type n);
  constexpr void swap(basic_string_view& s) noexcept;
  
  constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const;
  constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const;
  constexpr int compare(basic_string_view s) const noexcept;
  constexpr int compare(size_type pos1, size_type n1, basic_string_view s) const;
  constexpr int compare(size_type pos1, size_type n1, basic_string_view s,
                        size_type pos2, size_type n2) const;
  constexpr int compare(const charT* s) const;
  constexpr int compare(size_type pos1, size_type n1, const charT* s) const;
  constexpr int compare(size_type pos1, size_type n1, const charT* s, size_type n2) const;
  constexpr bool starts_with(basic_string_view x) const noexcept;
  constexpr bool starts_with(charT x) const noexcept;
  constexpr bool starts_with(const charT* x) const;
  constexpr bool ends_with(basic_string_view x) const noexcept;
  constexpr bool ends_with(charT x) const noexcept;
  constexpr bool ends_with(const charT* x) const;
  
  constexpr size_type find(basic_string_view s, size_type pos = 0) const noexcept;
  constexpr size_type find(charT c, size_type pos = 0) const noexcept;
  constexpr size_type find(const charT* s, size_type pos, size_type n) const;
  constexpr size_type find(const charT* s, size_type pos = 0) const;
  constexpr size_type rfind(basic_string_view s, size_type pos = npos) const noexcept;
  constexpr size_type rfind(charT c, size_type pos = npos) const noexcept;
  constexpr size_type rfind(const charT* s, size_type pos, size_type n) const;
  constexpr size_type rfind(const charT* s, size_type pos = npos) const;
  constexpr size_type find_first_of(basic_string_view s, size_type pos = 0) const noexcept;
  constexpr size_type find_first_of(charT c, size_type pos = 0) const noexcept;
  constexpr size_type find_first_of(const charT* s, size_type pos, size_type n) const;
  constexpr size_type find_first_of(const charT* s, size_type pos = 0) const;
  constexpr size_type find_last_of(basic_string_view s, size_type pos = npos) const noexcept;
  constexpr size_type find_last_of(charT c, size_type pos = npos) const noexcept;
  constexpr size_type find_last_of(const charT* s, size_type pos, size_type n) const;
  constexpr size_type find_last_of(const charT* s, size_type pos = npos) const;
  constexpr size_type find_first_not_of(basic_string_view s, size_type pos = 0) const noexcept;
  constexpr size_type find_first_not_of(charT c, size_type pos = 0) const noexcept;
  constexpr size_type find_first_not_of(const charT* s, size_type pos,
                                        size_type n) const;
  constexpr size_type find_first_not_of(const charT* s, size_type pos = 0) const;
  constexpr size_type find_last_not_of(basic_string_view s,
                                       size_type pos = npos) const noexcept;
  constexpr size_type find_last_not_of(charT c, size_type pos = npos) const noexcept;
  constexpr size_type find_last_not_of(const charT* s, size_type pos,
                                       size_type n) const;
  constexpr size_type find_last_not_of(const charT* s, size_type pos = npos) const;
private:
  const_pointer data_;          
  size_type size_;              
};
template<class It, class End>
  basic_string_view(It, End) -> basic_string_view<iter_value_t<It>>;
In every specialization 
basic_string_view<charT, traits>, the type 
traits shall meet the character traits requirements (
[char.traits])
.[ 
Note: The program is ill-formed if 
traits::char_type is not the same type as 
charT. — 
end note  ]
For a 
basic_string_view str,
any operation that invalidates a pointer
in the range 
[str.data(), str.data() + str.size())
invalidates pointers, iterators, and references
returned from 
str's member functions
.The complexity of 
basic_string_view member functions is 
O(1)
unless otherwise specified
.constexpr basic_string_view() noexcept;
Postconditions: 
size_ == 0 and 
data_ == nullptr. constexpr basic_string_view(const charT* str);
Preconditions: 
[str, str + traits::length(str)) is a valid range
. Effects: 
Constructs a 
basic_string_view, initializing 
data_ with 
str
and initializing 
size_ with 
traits::length(str). Complexity: 
O(traits::length(str)). constexpr basic_string_view(const charT* str, size_type len);
Preconditions: 
[str, str + len) is a valid range
. Effects: 
Constructs a 
basic_string_view, initializing 
data_ with 
str
and initializing 
size_ with 
len. template<class It, class End>
  constexpr basic_string_view(It begin, End end);
Constraints: 
- It satisfies contiguous_iterator.
- End satisfies sized_sentinel_for<It>.
- is_same_v<iter_value_t<It>, charT> is true.
- is_convertible_v<End, size_type> is false.
 Preconditions: 
- [begin, end) is a valid range.
- It models contiguous_iterator.
- End models sized_sentinel_for<It>.
 Effects: 
Initializes 
data_ with 
to_address(begin) and
initializes 
size_ with 
end - begin. using const_iterator = implementation-defined;
constexpr const_iterator begin() const noexcept;
constexpr const_iterator cbegin() const noexcept;
Returns: 
An iterator such that
- if !empty(), addressof(*begin()) == data_,
- otherwise, an unspecified value such that [begin(), end()) is a valid range.
 constexpr const_iterator end() const noexcept;
constexpr const_iterator cend() const noexcept;
Returns: 
begin() + size(). constexpr const_reverse_iterator rbegin() const noexcept;
constexpr const_reverse_iterator crbegin() const noexcept;
Returns: 
const_reverse_iterator(end()). constexpr const_reverse_iterator rend() const noexcept;
constexpr const_reverse_iterator crend() const noexcept;
Returns: 
const_reverse_iterator(begin()). constexpr size_type size() const noexcept;
constexpr size_type length() const noexcept;
constexpr size_type max_size() const noexcept;
Returns: 
The largest possible number of char-like objects that can be referred to by a 
basic_string_view. [[nodiscard]] constexpr bool empty() const noexcept;
constexpr const_reference operator[](size_type pos) const;
Preconditions: 
pos < size(). [ 
Note: Unlike 
basic_string::operator[],
basic_string_view::operator[](size()) has undefined behavior instead of returning 
charT(). — 
end note  ]
constexpr const_reference at(size_type pos) const;
Throws: 
out_of_range if 
pos >= size(). constexpr const_reference front() const;
constexpr const_reference back() const;
Returns: 
data_[size() - 1]. constexpr const_pointer data() const noexcept;
[ 
Note: Unlike 
basic_string::data() and 
string-literals,
data() may return a pointer to a buffer that is not null-terminated
.Therefore it is typically a mistake to pass 
data() to a function that takes just a 
const charT* and expects a null-terminated string
. — 
end note  ]
constexpr void remove_prefix(size_type n);
Preconditions: 
n <= size(). Effects: 
Equivalent to: data_ += n; size_ -= n;
constexpr void remove_suffix(size_type n);
Preconditions: 
n <= size(). Effects: 
Equivalent to: size_ -= n;
constexpr void swap(basic_string_view& s) noexcept;
Effects: 
Exchanges the values of 
*this and 
s. constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const;
Let 
rlen be the smaller of 
n and 
size() - pos.Throws: 
out_of_range if 
pos > size(). Preconditions: 
[s, s + rlen) is a valid range
. Effects: 
Equivalent to 
traits::copy(s, data() + pos, rlen). constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const;
Let 
rlen be the smaller of 
n and 
size() - pos.Throws: 
out_of_range if 
pos > size(). Effects: 
Determines 
rlen, the effective length of the string to reference
. Returns: 
basic_string_view(data() + pos, rlen). constexpr int compare(basic_string_view str) const noexcept;
Let 
rlen be the smaller of 
size() and 
str.size().Effects: 
Determines 
rlen, the effective length of the strings to compare
.  The function then compares the two strings by calling 
traits::compare(data(), str.data(), rlen).Returns: 
The nonzero result if the result of the comparison is nonzero
.  Otherwise, returns a value as indicated in Table 
70.Table 
70: 
compare() results   [tab:string.view.compare]
| Condition | Return Value | 
| size() < str.size() | < 0 | 
| size() == str.size() |   0 | 
| size() >  str.size() | > 0 | 
constexpr int compare(size_type pos1, size_type n1, basic_string_view str) const;
Effects: 
Equivalent to: return substr(pos1, n1).compare(str);
constexpr int compare(size_type pos1, size_type n1, basic_string_view str,
                      size_type pos2, size_type n2) const;
Effects: 
Equivalent to: return substr(pos1, n1).compare(str.substr(pos2, n2));
constexpr int compare(const charT* s) const;
Effects: 
Equivalent to: return compare(basic_string_view(s));
constexpr int compare(size_type pos1, size_type n1, const charT* s) const;
Effects: 
Equivalent to: return substr(pos1, n1).compare(basic_string_view(s));
constexpr int compare(size_type pos1, size_type n1, const charT* s, size_type n2) const;
Effects: 
Equivalent to: return substr(pos1, n1).compare(basic_string_view(s, n2));
constexpr bool starts_with(basic_string_view x) const noexcept;
Effects: 
Equivalent to: return substr(0, x.size()) == x;
constexpr bool starts_with(charT x) const noexcept;
Effects: 
Equivalent to: return !empty() && traits::eq(front(), x);
constexpr bool starts_with(const charT* x) const;
Effects: 
Equivalent to: return starts_with(basic_string_view(x));
constexpr bool ends_with(basic_string_view x) const noexcept;
Effects: 
Equivalent to:
return size() >= x.size() && compare(size() - x.size(), npos, x) == 0;
 constexpr bool ends_with(charT x) const noexcept;
Effects: 
Equivalent to: return !empty() && traits::eq(back(), x);
constexpr bool ends_with(const charT* x) const;
Effects: 
Equivalent to: return ends_with(basic_string_view(x));
Member functions in this subclause have complexity 
O(size() * str.size()) at worst,
although implementations should do better
.Let 
F be one of
find,
rfind,
find_first_of,
find_last_of,
find_first_not_of,
and
find_last_not_of.- Each member function of the form
 - 
constexpr return-type F(const charT* s, size_type pos) const;
 - 
has effects equivalent to:  return F(basic_string_view(s), pos);
- Each member function of the form
 - 
constexpr return-type F(const charT* s, size_type pos, size_type n) const;
 - 
has effects equivalent to:  return F(basic_string_view(s, n), pos);
- Each member function of the form
 - 
constexpr return-type F(charT c, size_type pos) const noexcept;
 - 
has effects equivalent to:  return F(basic_string_view(addressof(c), 1), pos);
constexpr size_type find(basic_string_view str, size_type pos = 0) const noexcept;
Let 
xpos be the lowest position, if possible, such that the following conditions hold:
- pos <= xpos
- xpos + str.size() <= size()
- traits::eq(at(xpos + I), str.at(I)) for all elements I of the string referenced by str.
Effects: 
Determines 
xpos. Returns: 
xpos if the function can determine such a value for 
xpos.  constexpr size_type rfind(basic_string_view str, size_type pos = npos) const noexcept;
Let 
xpos be the highest position, if possible, such that the following conditions hold:
- xpos <= pos
- xpos + str.size() <= size()
- traits::eq(at(xpos + I), str.at(I)) for all elements I of the string referenced by str.
Effects: 
Determines 
xpos. Returns: 
xpos if the function can determine such a value for 
xpos.  constexpr size_type find_first_of(basic_string_view str, size_type pos = 0) const noexcept;
Let 
xpos be the lowest position, if possible, such that the following conditions hold:
- pos <= xpos
- xpos < size()
- traits::eq(at(xpos), str.at(I)) for some element I of the string referenced by str.
Effects: 
Determines 
xpos. Returns: 
xpos if the function can determine such a value for 
xpos.  constexpr size_type find_last_of(basic_string_view str, size_type pos = npos) const noexcept;
Let 
xpos be the highest position, if possible, such that the following conditions hold:
- xpos <= pos
- xpos < size()
- traits::eq(at(xpos), str.at(I)) for some element I of the string referenced by str.
Effects: 
Determines 
xpos. Returns: 
xpos if the function can determine such a value for 
xpos.  constexpr size_type find_first_not_of(basic_string_view str, size_type pos = 0) const noexcept;
Let 
xpos be the lowest position, if possible, such that the following conditions hold:
- pos <= xpos
- xpos < size()
- traits::eq(at(xpos), str.at(I)) for no element I of the string referenced by str.
Effects: 
Determines 
xpos. Returns: 
xpos if the function can determine such a value for 
xpos.  constexpr size_type find_last_not_of(basic_string_view str, size_type pos = npos) const noexcept;
Let 
xpos be the highest position, if possible, such that the following conditions hold:
- xpos <= pos
- xpos < size()
- traits::eq(at(xpos), str.at(I)) for no element I of the string referenced by str.
Effects: 
Determines 
xpos. Returns: 
xpos if the function can determine such a value for 
xpos.