Add `std::string_view` replacement (`bpstd::string_view`)
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Tue, 8 Dec 2020 14:48:44 +0000 (09:48 -0500)
committerPhilippe Proulx <eeppeliteloop@gmail.com>
Fri, 28 Jan 2022 16:22:26 +0000 (11:22 -0500)
This patch adds an `std::string_view` replacement, `bpstd::string_view`,
which comes from the MIT-licensed
<https://github.com/bitwizeshift/string_view-standalone> project.

Babeltrace 2 cannot use `std::string_view` as it's part of C++17,
whereas the project only requires C++11.

`bpstd::basic_string_view` and `bpstd::string_view` are meant to work
like C++17's `std::basic_string_view` and `std::string_view`.

In any Babeltrace 2 C++ file, include it like this:

    #include "cpp-common/string_view.hpp"

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Change-Id: Icd9329fb55959de92832f4715b02359e1ef44184
Reviewed-on: https://review.lttng.org/c/babeltrace/+/4519

src/cpp-common/Makefile.am
src/cpp-common/string_view.hpp [new file with mode: 0644]

index 8c020c15498c240081aacd82c06adf513455bdb9..a61c1d1614fdeaf62e614f43d7af9a9912115308 100644 (file)
@@ -1,3 +1,3 @@
 # SPDX-License-Identifier: MIT
 
-EXTRA_DIST = bt2 optional.hpp
+EXTRA_DIST = bt2 optional.hpp string_view.hpp
diff --git a/src/cpp-common/string_view.hpp b/src/cpp-common/string_view.hpp
new file mode 100644 (file)
index 0000000..4c26e49
--- /dev/null
@@ -0,0 +1,1428 @@
+/*
+ * Copyright (c) 2016 Matthew Rodusek <http://rodusek.me>
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+/**
+ * \file string_view.hpp
+ *
+ * \brief This header contains the definition of the string_view type, as
+ *        described by the C++17 standard.
+ *
+ * \author Matthew Rodusek (matthew.rodusek@gmail.com)
+ * \copyright Matthew Rodusek
+ */
+
+/*
+ * The MIT License (MIT)
+ *
+ * Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+ * Copyright (c) 2016 Matthew Rodusek <http://rodusek.me>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef BPSTD_STRING_VIEW_HPP
+#define BPSTD_STRING_VIEW_HPP
+
+#include <algorithm>  // std::
+#include <string>     // std::char_traits
+#include <ostream>    // std::basic_ostream
+#include <cstddef>    // std::size_t
+#include <memory>     // std::allocator
+#include <stdexcept>  // std::out_of_range
+#include <iterator>   // std::reverse_iterator
+namespace bpstd { // back-port std
+
+  ////////////////////////////////////////////////////////////////////////////
+  /// \brief A wrapper around non-owned strings.
+  ///
+  /// This is an implementation of the C++17 string_view proposal
+  ///
+  /// \ingroup core
+  ////////////////////////////////////////////////////////////////////////////
+  template<
+    typename CharT,
+    typename Traits = std::char_traits<CharT>
+  >
+  class basic_string_view final
+  {
+    //------------------------------------------------------------------------
+    // Public Member Types
+    //------------------------------------------------------------------------
+  public:
+
+    using char_type   = CharT;
+    using traits_type = Traits;
+    using size_type   = std::size_t;
+
+    using value_type      = CharT;
+    using reference       = value_type&;
+    using const_reference = const value_type&;
+    using pointer         = value_type*;
+    using const_pointer   = const value_type*;
+
+    using iterator       = const CharT*;
+    using const_iterator = const CharT*;
+    using reverse_iterator = std::reverse_iterator<iterator>;
+    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+    //------------------------------------------------------------------------
+    // Public Members
+    //------------------------------------------------------------------------
+  public:
+
+    static constexpr size_type npos = size_type(-1);
+
+    //------------------------------------------------------------------------
+    // Constructors
+    //------------------------------------------------------------------------
+  public:
+
+    /// \brief Default constructs a basic_string_view without any content
+    constexpr basic_string_view() noexcept;
+
+    /// \brief Constructs a basic_string_view by copying another one
+    ///
+    /// \param other the string view being copied
+    constexpr basic_string_view(const basic_string_view& other) noexcept = default;
+
+    /// \brief Constructs a basic_string_view by moving anothe rone
+    ///
+    /// \param other the string view being moved
+    constexpr basic_string_view(basic_string_view&& other) noexcept = default;
+
+    /// \brief Constructs a basic_string_view from a std::basic_string
+    ///
+    /// \param str the string to view
+    template<typename Allocator>
+    basic_string_view(const std::basic_string<CharT,Traits,Allocator>& str) noexcept;
+
+    /// \brief Constructs a basic_string_view from an ansi-string
+    ///
+    /// \param str the string to view
+    constexpr basic_string_view(const char_type* str) noexcept;
+
+    /// \brief Constructs a basic_string_view from an ansi string of a given size
+    ///
+    /// \param str the string to view
+    /// \param count the size of the string
+    constexpr basic_string_view(const char_type* str, size_type count) noexcept;
+
+    //------------------------------------------------------------------------
+    // Assignment
+    //------------------------------------------------------------------------
+  public:
+
+    /// \brief Assigns a basic_string_view from an ansi-string
+    ///
+    /// \param view the string to view
+    /// \return reference to \c (*this)
+    basic_string_view& operator=(const basic_string_view& view) = default;
+
+    //------------------------------------------------------------------------
+    // Capacity
+    //------------------------------------------------------------------------
+  public:
+
+    /// \brief Returns the length of the string, in terms of bytes
+    ///
+    /// \return the length of the string, in terms of bytes
+    constexpr size_type size() const noexcept;
+
+    /// \copydoc basic_string_view::size
+    constexpr size_type length() const noexcept;
+
+    /// \brief The largest possible number of char-like objects that can be
+    ///        referred to by a basic_string_view.
+    /// \return Maximum number of characters
+    constexpr size_type max_size() const noexcept;
+
+    /// \brief Returns whether the basic_string_view is empty
+    ///        (i.e. whether its length is 0).
+    ///
+    /// \return whether the basic_string_view is empty
+    constexpr bool empty() const noexcept;
+
+    //------------------------------------------------------------------------
+    // Element Access
+    //------------------------------------------------------------------------
+  public:
+
+    /// \brief Gets the ansi-string of the current basic_string_view
+    ///
+    /// \return the ansi-string pointer
+    constexpr const char_type* c_str() const noexcept;
+
+    /// \brief Gets the data of the current basic_string_view
+    ///
+    /// \note This is an alias of #c_str
+    ///
+    /// \return the data this basic_string_view contains
+    constexpr const char_type* data() const noexcept;
+
+    /// \brief Accesses the element at index \p pos
+    ///
+    /// \param pos the index to access
+    /// \return const reference to the character
+    constexpr const_reference operator[](size_type pos) const noexcept;
+
+    /// \brief Accesses the element at index \p pos
+    ///
+    /// \param pos the index to access
+    /// \return const reference to the character
+    constexpr const_reference at(size_type pos) const;
+
+    /// \brief Access the first character of the string
+    ///
+    /// \note Undefined behavior if basic_string_view is empty
+    ///
+    /// \return reference to the first character of the string
+    constexpr const_reference front() const noexcept;
+
+    /// \brief References the last character of the string
+    ///
+    /// \note Undefined behavior if basic_string_view is empty
+    ///
+    /// \return reference to the last character of the string
+    constexpr const_reference back() const noexcept;
+
+    //------------------------------------------------------------------------
+    // Modifiers
+    //------------------------------------------------------------------------
+  public:
+
+    /// \brief Moves the start of the view forward by n characters.
+    ///
+    /// The behavior is undefined if n > size().
+    ///
+    /// \param n number of characters to remove from the start of the view
+    void remove_prefix(size_type n) noexcept;
+
+    /// \brief Moves the end of the view back by n characters.
+    ///
+    /// The behavior is undefined if n > size().
+    ///
+    /// \param n number of characters to remove from the end of the view
+    void remove_suffix(size_type n) noexcept;
+
+    /// \brief Exchanges the view with that of v.
+    ///
+    /// \param v view to swap with
+    void swap(basic_string_view& v) noexcept;
+
+    //------------------------------------------------------------------------
+    // Conversions
+    //------------------------------------------------------------------------
+  public:
+
+    /// \brief Creates a basic_string with a copy of the content of the current view.
+    ///
+    /// \tparam Allocator type used to allocate internal storage
+    /// \param a Allocator instance to use for allocating the new string
+    ///
+    /// \return A basic_string containing a copy of the characters of the current view.
+    template<class Allocator = std::allocator<CharT>>
+    constexpr std::basic_string<CharT, Traits, Allocator>
+      to_string(const Allocator& a = Allocator()) const;
+
+    /// \copydoc basic_string_view::to_string
+    template<class Allocator>
+    explicit constexpr operator std::basic_string<CharT, Traits, Allocator>() const;
+
+    //------------------------------------------------------------------------
+    // Operations
+    //------------------------------------------------------------------------
+  public:
+
+    /// \brief Copies the substring [pos, pos + rcount) to the character string pointed
+    ///        to by dest, where rcount is the smaller of count and size() - pos.
+    ///
+    /// \param dest pointer to the destination character string
+    /// \param count requested substring length
+    /// \param pos position of the first character
+    size_type copy( char_type* dest,
+                    size_type count = npos,
+                    size_type pos = 0 ) const;
+
+    /// \brief Returns a substring of this viewed string
+    ///
+    /// \param pos the position of the first character in the substring
+    /// \param len the length of the substring
+    /// \return the created substring
+    basic_string_view substr(size_t pos = 0, size_t len = npos) const;
+
+    //------------------------------------------------------------------------
+
+    /// \brief Compares two character sequences
+    ///
+    /// \param v view to compare
+    /// \return negative value if this view is less than the other character
+    ///         sequence, zero if the both character sequences are equal, positive
+    ///         value if this view is greater than the other character sequence.
+    int compare(basic_string_view v) const noexcept;
+
+    /// \brief Compares two character sequences
+    ///
+    /// \param pos   position of the first character in this view to compare
+    /// \param count number of characters of this view to compare
+    /// \param v     view to compare
+    /// \return negative value if this view is less than the other character
+    ///         sequence, zero if the both character sequences are equal, positive
+    ///         value if this view is greater than the other character sequence.
+    int compare(size_type pos, size_type count, basic_string_view v) const;
+
+    /// \brief Compares two character sequences
+    ///
+    /// \param pos1   position of the first character in this view to compare
+    /// \param count1 number of characters of this view to compare
+    /// \param v      view to compare
+    /// \param pos2   position of the second character in this view to compare
+    /// \param count2 number of characters of the given view to compare
+    /// \return negative value if this view is less than the other character
+    ///         sequence, zero if the both character sequences are equal, positive
+    ///         value if this view is greater than the other character sequence.
+    int compare( size_type pos1, size_type count1, basic_string_view v,
+                 size_type pos2, size_type count2 ) const;
+
+    /// \brief Compares two character sequences
+    ///
+    /// \param s pointer to the character string to compare to
+    /// \return negative value if this view is less than the other character
+    ///         sequence, zero if the both character sequences are equal, positive
+    ///         value if this view is greater than the other character sequence.
+    int compare(const char_type* s) const;
+
+    /// \brief Compares two character sequences
+    ///
+    /// \param pos   position of the first character in this view to compare
+    /// \param count number of characters of this view to compare
+    /// \param s pointer to the character string to compare to
+    /// \return negative value if this view is less than the other character
+    ///         sequence, zero if the both character sequences are equal, positive
+    ///         value if this view is greater than the other character sequence.
+    int compare(size_type pos, size_type count, const char_type* s) const;
+
+    /// \brief Compares two character sequences
+    ///
+    /// \param pos   position of the first character in this view to compare
+    /// \param count1 number of characters of this view to compare
+    /// \param s pointer to the character string to compare to
+    /// \param count2 number of characters of the given view to compare
+    /// \return negative value if this view is less than the other character
+    ///         sequence, zero if the both character sequences are equal, positive
+    ///         value if this view is greater than the other character sequence.
+    int compare( size_type pos, size_type count1, const char_type* s,
+                 size_type count2 ) const;
+
+    //------------------------------------------------------------------------
+
+    size_type find(basic_string_view v, size_type pos = 0) const;
+
+    size_type find(char_type c, size_type pos = 0) const;
+
+    size_type find(const char_type* s, size_type pos, size_type count) const;
+
+    size_type find(const char_type* s, size_type pos = 0) const;
+
+    //------------------------------------------------------------------------
+
+    size_type rfind(basic_string_view v, size_type pos = npos) const;
+
+    size_type rfind(char_type c, size_type pos = npos) const;
+
+    size_type rfind(const char_type* s, size_type pos, size_type count) const;
+
+    size_type rfind(const char_type* s, size_type pos = npos) const;
+
+    //------------------------------------------------------------------------
+
+    size_type find_first_of(basic_string_view v, size_type pos = 0) const;
+
+    size_type find_first_of(char_type c, size_type pos = 0) const;
+
+    size_type find_first_of(const char_type* s, size_type pos, size_type count) const;
+
+    size_type find_first_of(const char_type* s, size_type pos = 0) const;
+
+    //------------------------------------------------------------------------
+
+    size_type find_last_of(basic_string_view v, size_type pos = npos) const;
+
+    size_type find_last_of(char_type c, size_type pos = npos) const;
+
+    size_type find_last_of(const char_type* s, size_type pos, size_type count) const;
+
+    size_type find_last_of(const char_type* s, size_type pos = npos) const;
+
+    //------------------------------------------------------------------------
+
+    size_type find_first_not_of(basic_string_view v, size_type pos = 0) const;
+
+    size_type find_first_not_of(char_type c, size_type pos = 0) const;
+
+    size_type find_first_not_of(const char_type* s, size_type pos, size_type count) const;
+
+    size_type find_first_not_of(const char_type* s, size_type pos = 0) const;
+
+    //------------------------------------------------------------------------
+
+    size_type find_last_not_of(basic_string_view v, size_type pos = npos) const;
+
+    size_type find_last_not_of(char_type c, size_type pos = npos) const;
+
+    size_type find_last_not_of(const char_type* s, size_type pos, size_type count) const;
+
+    size_type find_last_not_of(const char_type* s, size_type pos = npos) const;
+
+    //------------------------------------------------------------------------
+    // Iterators
+    //------------------------------------------------------------------------
+  public:
+
+    /// \{
+    /// \brief Retrieves the begin iterator for this basic_string_view
+    ///
+    /// \return the begin iterator
+    const_iterator begin() const noexcept;
+    const_iterator cbegin() const noexcept;
+    /// \}
+
+    /// \{
+    /// \brief Retrieves the end iterator for this basic_string_view
+    ///
+    /// \return the end iterator
+    const_iterator end() const noexcept;
+    const_iterator cend() const noexcept;
+    /// \}
+
+    /// \{
+    /// \brief Retrieves the reverse begin iterator for this basic_string_view
+    ///
+    /// \return the reverse begin iterator
+    const_reverse_iterator rbegin() const noexcept;
+    const_reverse_iterator rend() const noexcept;
+    /// \}
+
+    /// \{
+    /// \brief Retrieves the reverse end iterator for this basic_string_view
+    ///
+    /// \return the reverse end iterator
+    const_reverse_iterator crbegin() const noexcept;
+    const_reverse_iterator crend() const noexcept;
+    /// \}
+
+    //------------------------------------------------------------------------
+    // Private Member
+    //------------------------------------------------------------------------
+  private:
+
+    const char_type* m_str;  ///< The internal string type
+    size_type        m_size; ///< The size of this string
+
+    /// \brief Checks whether \p c is one of the characters in \p str
+    ///
+    /// \param c the character to check
+    /// \param str the characters to compare against
+    /// \return true if \p c is one of the characters in \p str
+    static bool is_one_of(CharT c, basic_string_view str);
+  };
+
+  template <typename CharT, typename Traits>
+  const typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::npos;
+
+  //--------------------------------------------------------------------------
+  // Public Functions
+  //--------------------------------------------------------------------------
+
+  /// \brief Overload for ostream output of basic_string_view
+  ///
+  /// \param o   The output stream to print to
+  /// \param str the string to print
+  /// \return reference to the output stream
+  template<typename CharT, typename Traits>
+  std::basic_ostream<CharT,Traits>& operator<<(std::basic_ostream<CharT,Traits>& o,
+                                               const basic_string_view<CharT,Traits>& str);
+
+  template<typename CharT, typename Traits>
+  void swap(basic_string_view<CharT,Traits>& lhs,
+            basic_string_view<CharT,Traits>& rhs) noexcept;
+
+  //--------------------------------------------------------------------------
+  // Comparison Functions
+  //--------------------------------------------------------------------------
+
+  template<typename CharT, typename Traits>
+  bool operator==(const basic_string_view<CharT,Traits>& lhs,
+                  const basic_string_view<CharT,Traits>& rhs) noexcept;
+  template<typename CharT, typename Traits>
+  bool operator!=(const basic_string_view<CharT,Traits>& lhs,
+                  const basic_string_view<CharT,Traits>& rhs) noexcept;
+  template<typename CharT, typename Traits>
+  bool operator<(const basic_string_view<CharT,Traits>& lhs,
+                 const basic_string_view<CharT,Traits>& rhs) noexcept;
+  template<typename CharT, typename Traits>
+  bool operator>(const basic_string_view<CharT,Traits>& lhs,
+                 const basic_string_view<CharT,Traits>& rhs) noexcept;
+  template<typename CharT, typename Traits>
+  bool operator<=(const basic_string_view<CharT,Traits>& lhs,
+                  const basic_string_view<CharT,Traits>& rhs) noexcept;
+  template<typename CharT, typename Traits>
+  bool operator>=(const basic_string_view<CharT,Traits>& lhs,
+                  const basic_string_view<CharT,Traits>& rhs) noexcept;
+
+  //--------------------------------------------------------------------------
+  // Type Aliases
+  //--------------------------------------------------------------------------
+
+  using string_view    = basic_string_view<char>;
+  using wstring_view   = basic_string_view<wchar_t>;
+  using u16string_view = basic_string_view<char16_t>;
+  using u32string_view = basic_string_view<char32_t>;
+
+} // namespace bpstd
+
+#ifndef BPSTD_DETAIL_STRING_VIEW_INL
+#define BPSTD_DETAIL_STRING_VIEW_INL
+
+namespace bpstd {
+
+  //--------------------------------------------------------------------------
+  // Constructor
+  //--------------------------------------------------------------------------
+
+  template<typename CharT, typename Traits>
+  inline constexpr basic_string_view<CharT,Traits>::basic_string_view()
+    noexcept
+    : m_str(nullptr),
+      m_size(0)
+  {
+
+  }
+
+  template<typename CharT, typename Traits>
+  template<typename Allocator>
+  inline basic_string_view<CharT,Traits>::basic_string_view(const std::basic_string<CharT,Traits,Allocator>& str)
+    noexcept
+    : m_str(str.c_str()),
+      m_size(str.size())
+  {
+
+  }
+
+  template<typename CharT, typename Traits>
+  inline constexpr basic_string_view<CharT,Traits>::basic_string_view(const char_type* str)
+    noexcept
+    : m_str(str),
+      m_size(traits_type::length(str))
+  {
+
+  }
+
+  template<typename CharT, typename Traits>
+  inline constexpr basic_string_view<CharT,Traits>::basic_string_view(const char_type* str, size_type count)
+    noexcept
+    : m_str(str),
+      m_size(count)
+  {
+
+  }
+
+  //--------------------------------------------------------------------------
+  // Capacity
+  //--------------------------------------------------------------------------
+
+  template<typename CharT, typename Traits>
+  inline constexpr typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::size()
+    const noexcept
+  {
+    return m_size;
+  }
+
+  template<typename CharT, typename Traits>
+  inline constexpr typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::length()
+    const noexcept
+  {
+    return size();
+  }
+
+  template<typename CharT, typename Traits>
+  inline constexpr typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::max_size()
+    const noexcept
+  {
+    return npos - 1;
+  }
+
+  template<typename CharT, typename Traits>
+  inline constexpr bool basic_string_view<CharT,Traits>::empty()
+    const noexcept
+  {
+    return m_size == 0;
+  }
+
+  //--------------------------------------------------------------------------
+  // Element Access
+  //--------------------------------------------------------------------------
+
+  template<typename CharT, typename Traits>
+  inline constexpr const typename basic_string_view<CharT,Traits>::char_type*
+    basic_string_view<CharT,Traits>::c_str()
+    const noexcept
+  {
+    return m_str;
+  }
+
+  template<typename CharT, typename Traits>
+  inline constexpr const typename basic_string_view<CharT,Traits>::char_type*
+    basic_string_view<CharT,Traits>::data()
+    const noexcept
+  {
+    return m_str;
+  }
+
+  template<typename CharT, typename Traits>
+  inline constexpr typename basic_string_view<CharT,Traits>::const_reference
+    basic_string_view<CharT,Traits>::operator[](size_type pos)
+    const noexcept
+  {
+    return m_str[pos];
+  }
+
+  template<typename CharT, typename Traits>
+  inline constexpr typename basic_string_view<CharT,Traits>::const_reference
+    basic_string_view<CharT,Traits>::at(size_type pos)
+    const
+  {
+    return pos < m_size ? m_str[pos] : throw std::out_of_range("Input out of range in basic_string_view::at"), m_str[pos];
+  }
+
+  template<typename CharT, typename Traits>
+  inline constexpr typename basic_string_view<CharT,Traits>::const_reference
+    basic_string_view<CharT,Traits>::front( )
+    const noexcept
+  {
+    return *m_str;
+  }
+
+  template<typename CharT, typename Traits>
+  inline constexpr typename basic_string_view<CharT,Traits>::const_reference
+    basic_string_view<CharT,Traits>::back( )
+    const noexcept
+  {
+    return m_str[m_size-1];
+  }
+
+  //--------------------------------------------------------------------------
+  // Modifiers
+  //--------------------------------------------------------------------------
+
+  template<typename CharT, typename Traits>
+  inline void
+    basic_string_view<CharT,Traits>::remove_prefix(size_type n)
+    noexcept
+  {
+    m_str += n, m_size -= n;
+  }
+
+  template<typename CharT, typename Traits>
+  inline void
+    basic_string_view<CharT,Traits>::remove_suffix(size_type n)
+    noexcept
+  {
+    m_size -= n;
+  }
+
+  template<typename CharT, typename Traits>
+  inline void
+    basic_string_view<CharT,Traits>::swap(basic_string_view& v)
+    noexcept
+  {
+    using std::swap;
+    swap(m_size,v.m_size);
+    swap(m_str,v.m_str);
+  }
+
+  //--------------------------------------------------------------------------
+  // Conversions
+  //--------------------------------------------------------------------------
+
+  template<typename CharT, typename Traits>
+  template<class Allocator>
+  inline constexpr std::basic_string<CharT, Traits, Allocator>
+    basic_string_view<CharT,Traits>::to_string(const Allocator& a)
+    const
+  {
+    return std::basic_string<CharT,Traits,Allocator>(m_str, m_size, a);
+  }
+
+  template<typename CharT, typename Traits>
+  template<class Allocator>
+  inline constexpr basic_string_view<CharT,Traits>::operator
+    std::basic_string<CharT, Traits, Allocator>()
+    const
+  {
+    return std::basic_string<CharT,Traits,Allocator>(m_str, m_size);
+  }
+
+  //--------------------------------------------------------------------------
+  // String Operations
+  //--------------------------------------------------------------------------
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::copy(char_type* dest,
+                                          size_type count,
+                                          size_type pos)
+    const
+  {
+    if(pos >= m_size) {
+      throw std::out_of_range("Index out of range in basic_string_view::copy");
+    }
+
+    const size_type rcount = std::min(m_size - pos,count+1);
+    std::copy( m_str + pos, m_str + pos + rcount, dest);
+    return rcount;
+  }
+
+  template<typename CharT, typename Traits>
+  inline basic_string_view<CharT,Traits>
+    basic_string_view<CharT,Traits>::substr(size_type pos,
+                                            size_type len)
+    const
+  {
+    const size_type max_length = pos > m_size ? 0 : m_size - pos;
+
+    if (pos > size()) {
+      throw std::out_of_range("Index out of range in basic_string_view::substr");
+    }
+
+    return basic_string_view(m_str + pos, std::min(len, max_length) );
+  }
+
+  //--------------------------------------------------------------------------
+
+  template<typename CharT, typename Traits>
+  inline int basic_string_view<CharT,Traits>::compare(basic_string_view v)
+    const noexcept
+  {
+    const size_type rlen = std::min(m_size,v.m_size);
+    const int compare = Traits::compare(m_str,v.m_str,rlen);
+
+    return (compare ? compare : (m_size < v.m_size ? -1 : (m_size > v.m_size ? 1 : 0)));
+  }
+
+  template<typename CharT, typename Traits>
+  inline int basic_string_view<CharT,Traits>::compare(size_type pos,
+                                                      size_type count,
+                                                      basic_string_view v)
+    const
+  {
+    return substr(pos,count).compare(v);
+  }
+
+  template<typename CharT, typename Traits>
+  inline int basic_string_view<CharT,Traits>::compare(size_type pos1,
+                                                      size_type count1,
+                                                      basic_string_view v,
+                                                      size_type pos2,
+                                                      size_type count2)
+    const
+  {
+    return substr(pos1,count1).compare(v.substr(pos2,count2));
+  }
+
+  template<typename CharT, typename Traits>
+  inline int basic_string_view<CharT,Traits>::compare(const char_type* s)
+    const
+  {
+    return compare(basic_string_view<CharT,Traits>(s));
+  }
+
+  template<typename CharT, typename Traits>
+  inline int basic_string_view<CharT,Traits>::compare(size_type pos,
+                                                      size_type count,
+                                                      const char_type* s)
+    const
+  {
+    return substr(pos, count).compare(basic_string_view<CharT,Traits>(s));
+  }
+
+  template<typename CharT, typename Traits>
+  inline int basic_string_view<CharT,Traits>::compare(size_type pos,
+                                                      size_type count1,
+                                                      const char_type* s,
+                                                      size_type count2)
+    const
+  {
+    return substr(pos, count1).compare(basic_string_view<CharT,Traits>(s, count2));
+  }
+
+  //--------------------------------------------------------------------------
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::find(basic_string_view v,
+                                          size_type pos)
+    const
+  {
+    // Can't find a substring if the substring is bigger than this
+    if (pos > size()) {
+      return npos;
+    }
+    if ((pos + v.size()) > size()) {
+      return npos;
+    }
+
+    const auto offset = pos;
+    const auto increments = size() - v.size();
+
+    for (auto i = 0u; i <= increments; ++i) {
+      const auto j = i + offset;
+      if (substr(j, v.size()) == v) {
+        return j;
+      }
+    }
+    return npos;
+  }
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::find(char_type c,
+                                          size_type pos)
+    const
+  {
+    return find(basic_string_view<CharT,Traits>(&c, 1), pos);
+  }
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::find(const char_type* s, size_type pos,
+                                          size_type count)
+    const
+  {
+    return find(basic_string_view<CharT,Traits>(s, count), pos);
+  }
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::find(const char_type* s,
+                                          size_type pos)
+    const
+  {
+    return find(basic_string_view<CharT,Traits>(s), pos);
+  }
+
+  //--------------------------------------------------------------------------
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::rfind(basic_string_view v,
+                                           size_type pos)
+    const
+  {
+    if (empty()) {
+      return v.empty() ? 0u : npos;
+    }
+    if (v.empty()) {
+      return std::min(size() - 1, pos);
+    }
+    if (v.size() > size()) {
+      return npos;
+    }
+
+    auto i = std::min(pos, (size() - v.size()));
+    while (i != npos) {
+      if (substr(i, v.size()) == v) {
+        return i;
+      }
+      --i;
+    }
+
+    return npos;
+  }
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::rfind(char_type c,
+                                           size_type pos)
+    const
+  {
+    return rfind(basic_string_view<CharT,Traits>(&c, 1), pos);
+  }
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::rfind(const char_type* s, size_type pos,
+                                           size_type count)
+    const
+  {
+    return rfind(basic_string_view<CharT,Traits>(s, count), pos);
+  }
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::rfind(const char_type* s,
+                                           size_type pos)
+    const
+  {
+    return rfind(basic_string_view<CharT,Traits>(s), pos);
+  }
+
+  //--------------------------------------------------------------------------
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::find_first_of(basic_string_view v,
+                                                   size_type pos)
+    const
+  {
+    const auto max_index = size();
+    for (auto i = pos; i < max_index;  ++i) {
+      if (is_one_of(m_str[i],v)) {
+        return i;
+      }
+    }
+
+    return npos;
+  }
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::find_first_of(char_type c,
+                                                   size_type pos)
+    const
+  {
+    return find_first_of(basic_string_view<CharT,Traits>(&c, 1), pos);
+  }
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::find_first_of(const char_type* s, size_type pos,
+                                                   size_type count)
+    const
+  {
+    return find_first_of(basic_string_view<CharT,Traits>(s, count), pos);
+  }
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::find_first_of(const char_type* s,
+                                                   size_type pos)
+    const
+  {
+    return find_first_of(basic_string_view<CharT,Traits>(s), pos);
+  }
+
+  //--------------------------------------------------------------------------
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::find_last_of(basic_string_view v,
+                                                  size_type pos)
+    const
+  {
+    if (empty()) {
+      return npos;
+    }
+    const auto max_index = std::min(size() - 1, pos);
+    for (auto i = 0u; i <= max_index;  ++i) {
+      const auto j = max_index - i;
+
+      if (is_one_of(m_str[j],v)) {
+        return j;
+      }
+    }
+
+    return npos;
+  }
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::find_last_of(char_type c,
+                                                  size_type pos)
+    const
+  {
+    return find_last_of(basic_string_view<CharT,Traits>(&c, 1), pos);
+  }
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::find_last_of(const char_type* s, size_type pos,
+                                                  size_type count)
+    const
+  {
+    return find_last_of(basic_string_view<CharT,Traits>(s, count), pos);
+  }
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::find_last_of(const char_type* s,
+                                                  size_type pos)
+    const
+  {
+    return find_last_of(basic_string_view<CharT,Traits>(s), pos);
+  }
+
+  //--------------------------------------------------------------------------
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::find_first_not_of(basic_string_view v,
+                                                       size_type pos)
+    const
+  {
+    const auto max_index = size();
+    for (auto i = pos; i < max_index;  ++i) {
+      if (!is_one_of(m_str[i],v)) {
+        return i;
+      }
+    }
+
+    return npos;
+  }
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::find_first_not_of(char_type c,
+                                                       size_type pos)
+    const
+  {
+    return find_first_not_of(basic_string_view<CharT,Traits>(&c, 1), pos);
+  }
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::find_first_not_of(const char_type* s,
+                                                       size_type pos,
+                                                       size_type count)
+    const
+  {
+    return find_first_not_of(basic_string_view<CharT,Traits>(s, count), pos);
+  }
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::find_first_not_of(const char_type* s,
+                                                       size_type pos)
+    const
+  {
+    return find_first_not_of(basic_string_view<CharT,Traits>(s), pos);
+  }
+
+  //--------------------------------------------------------------------------
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::find_last_not_of(basic_string_view v,
+                                                      size_type pos)
+    const
+  {
+    if (empty()) {
+      return npos;
+    }
+    const auto max_index = std::min(size() - 1, pos);
+    for (auto i = 0u; i <= max_index;  ++i) {
+      const auto j = max_index - i;
+
+      if (!is_one_of(m_str[j],v)) {
+        return j;
+      }
+    }
+
+    return npos;
+  }
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::find_last_not_of(char_type c,
+                                                      size_type pos)
+    const
+  {
+    return find_last_not_of(basic_string_view<CharT,Traits>(&c, 1), pos);
+  }
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::find_last_not_of(const char_type* s,
+                                                      size_type pos,
+                                                      size_type count)
+    const
+  {
+    return find_last_not_of(basic_string_view<CharT,Traits>(s, count), pos);
+  }
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::size_type
+    basic_string_view<CharT,Traits>::find_last_not_of(const char_type* s,
+                                                      size_type pos)
+    const
+  {
+    return find_last_not_of(basic_string_view<CharT,Traits>(s), pos);
+  }
+
+  //--------------------------------------------------------------------------
+  // Iterator
+  //--------------------------------------------------------------------------
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::const_iterator
+    basic_string_view<CharT,Traits>::begin()
+    const noexcept
+  {
+    return m_str;
+  }
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::const_iterator
+    basic_string_view<CharT,Traits>::cbegin()
+    const noexcept
+  {
+    return begin();
+  }
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::const_iterator
+    basic_string_view<CharT,Traits>::end()
+    const noexcept
+  {
+    return m_str + m_size;
+  }
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::const_iterator
+    basic_string_view<CharT,Traits>::cend()
+    const noexcept
+  {
+    return cend();
+  }
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::const_reverse_iterator
+    basic_string_view<CharT,Traits>::rbegin()
+    const noexcept
+  {
+    return const_reverse_iterator{end()};
+  }
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::const_reverse_iterator
+    basic_string_view<CharT,Traits>::crbegin()
+    const noexcept
+  {
+    return rbegin();
+  }
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::const_reverse_iterator
+    basic_string_view<CharT,Traits>::rend()
+    const noexcept
+  {
+    return const_reverse_iterator{begin()};
+  }
+
+  template<typename CharT, typename Traits>
+  inline typename basic_string_view<CharT,Traits>::const_reverse_iterator
+    basic_string_view<CharT,Traits>::crend()
+    const noexcept
+  {
+    return crend();
+  }
+
+  template <typename CharT, typename Traits>
+  inline bool basic_string_view<CharT,Traits>::is_one_of(CharT c,
+                                                         basic_string_view str)
+  {
+    for (auto s : str) {
+      if (c == s) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  //--------------------------------------------------------------------------
+  // Public Functions
+  //--------------------------------------------------------------------------
+
+  template<typename CharT, typename Traits>
+  std::basic_ostream<CharT,Traits>& operator<<(std::basic_ostream<CharT,Traits>& o,
+                                               const basic_string_view<CharT,Traits>& str)
+  {
+    o.write(str.data(),str.size());
+    return o;
+  }
+
+  template<typename CharT, typename Traits>
+  inline void swap(basic_string_view<CharT,Traits>& lhs,
+                   basic_string_view<CharT,Traits>& rhs)
+    noexcept
+  {
+    lhs.swap(rhs);
+  }
+
+  //--------------------------------------------------------------------------
+  // Comparison Functions
+  //--------------------------------------------------------------------------
+
+  template<typename CharT, typename Traits>
+  inline bool operator==(const basic_string_view<CharT,Traits>& lhs,
+                         const basic_string_view<CharT,Traits>& rhs)
+    noexcept
+  {
+    return lhs.compare(rhs) == 0;
+  }
+
+  template<typename CharT, typename Traits>
+  inline bool operator==(basic_string_view<CharT,Traits> lhs,
+                         const CharT* rhs)
+    noexcept
+  {
+    return lhs == basic_string_view<CharT,Traits>(rhs);
+  }
+
+  template<typename CharT, typename Traits>
+  inline bool operator==(const CharT* lhs,
+                         const basic_string_view<CharT,Traits>& rhs)
+    noexcept
+  {
+    return basic_string_view<CharT,Traits>(lhs) == rhs;
+  }
+
+  template<typename CharT, typename Traits, typename Allocator>
+  inline bool operator==(const std::basic_string<CharT,Traits,Allocator>& lhs,
+                         const basic_string_view<CharT,Traits>& rhs)
+  {
+    return basic_string_view<CharT,Traits>(lhs) == rhs;
+  }
+
+  template<typename CharT, typename Traits, typename Allocator>
+  inline bool operator==(const basic_string_view<CharT,Traits>& lhs,
+                         const std::basic_string<CharT,Traits,Allocator>& rhs)
+  {
+    return lhs == basic_string_view<CharT,Traits>(rhs);
+  }
+
+  //--------------------------------------------------------------------------
+
+  template<typename CharT, typename Traits>
+  inline bool operator!=(const basic_string_view<CharT,Traits>& lhs,
+                         const basic_string_view<CharT,Traits>& rhs)
+    noexcept
+  {
+    return lhs.compare(rhs) != 0;
+  }
+
+  template<typename CharT, typename Traits>
+  inline bool operator!=(const basic_string_view<CharT,Traits>& lhs,
+                         const CharT* rhs)
+    noexcept
+  {
+    return lhs != basic_string_view<CharT,Traits>(rhs);
+  }
+
+  template<typename CharT, typename Traits>
+  inline bool operator!=(const CharT* lhs,
+                         const basic_string_view<CharT,Traits>& rhs)
+    noexcept
+  {
+    return basic_string_view<CharT,Traits>(lhs) != rhs;
+  }
+
+  template<typename CharT, typename Traits, typename Allocator>
+  inline bool operator!=(const std::basic_string<CharT,Traits,Allocator>& lhs,
+                         const basic_string_view<CharT,Traits>& rhs)
+  {
+    return basic_string_view<CharT,Traits>(lhs) != rhs;
+  }
+
+  template<typename CharT, typename Traits, typename Allocator>
+  inline bool operator!=(const basic_string_view<CharT,Traits>& lhs,
+                         const std::basic_string<CharT,Traits,Allocator>& rhs)
+  {
+    return lhs != basic_string_view<CharT,Traits>(rhs);
+  }
+  //--------------------------------------------------------------------------
+
+  template<typename CharT, typename Traits>
+  inline bool operator<(const basic_string_view<CharT,Traits>& lhs,
+                        const basic_string_view<CharT,Traits>& rhs)
+    noexcept
+  {
+    return lhs.compare(rhs) < 0;
+  }
+
+  template<typename CharT, typename Traits>
+  inline bool operator<(const basic_string_view<CharT,Traits>& lhs,
+                        const CharT* rhs)
+    noexcept
+  {
+    return lhs < basic_string_view<CharT,Traits>(rhs);
+  }
+
+  template<typename CharT, typename Traits>
+  inline bool operator<(const CharT* lhs,
+                        const basic_string_view<CharT,Traits>& rhs)
+    noexcept
+  {
+    return basic_string_view<CharT,Traits>(lhs) < rhs;
+  }
+
+  template<typename CharT, typename Traits, typename Allocator>
+  inline bool operator<(const std::basic_string<CharT,Traits,Allocator>& lhs,
+                        const basic_string_view<CharT,Traits>& rhs)
+  {
+    return basic_string_view<CharT,Traits>(lhs) < rhs;
+  }
+
+  template<typename CharT, typename Traits, typename Allocator>
+  inline bool operator<(const basic_string_view<CharT,Traits>& lhs,
+                        const std::basic_string<CharT,Traits,Allocator>& rhs)
+  {
+    return lhs < basic_string_view<CharT,Traits>(rhs);
+  }
+
+  //--------------------------------------------------------------------------
+
+  template<typename CharT, typename Traits>
+  inline bool operator>(const basic_string_view<CharT,Traits>& lhs,
+                        const basic_string_view<CharT,Traits>& rhs)
+    noexcept
+  {
+    return lhs.compare(rhs) > 0;
+  }
+
+  template<typename CharT, typename Traits>
+  inline bool operator>(const basic_string_view<CharT,Traits>& lhs,
+                        const CharT* rhs)
+    noexcept
+  {
+    return lhs > basic_string_view<CharT,Traits>(rhs);
+  }
+
+  template<typename CharT, typename Traits>
+  inline bool operator>(const CharT* lhs,
+                        const basic_string_view<CharT,Traits>& rhs)
+    noexcept
+  {
+    return basic_string_view<CharT,Traits>(lhs) > rhs;
+  }
+
+  template<typename CharT, typename Traits, typename Allocator>
+  inline bool operator>(const std::basic_string<CharT,Traits,Allocator>& lhs,
+                        const basic_string_view<CharT,Traits>& rhs)
+  {
+    return basic_string_view<CharT,Traits>(lhs) > rhs;
+  }
+
+  template<typename CharT, typename Traits, typename Allocator>
+  inline bool operator>(const basic_string_view<CharT,Traits>& lhs,
+                        const std::basic_string<CharT,Traits,Allocator>& rhs)
+  {
+    return lhs > basic_string_view<CharT,Traits>(rhs);
+  }
+
+  //--------------------------------------------------------------------------
+
+  template<typename CharT, typename Traits>
+  inline bool operator<=(const basic_string_view<CharT,Traits>& lhs,
+                         const basic_string_view<CharT,Traits>& rhs)
+    noexcept
+  {
+    return lhs.compare(rhs) <= 0;
+  }
+
+  template<typename CharT, typename Traits>
+  inline bool operator<=(const basic_string_view<CharT,Traits>& lhs,
+                         const CharT* rhs)
+    noexcept
+  {
+    return lhs <= basic_string_view<CharT,Traits>(rhs);
+  }
+
+  template<typename CharT, typename Traits>
+  inline bool operator<=(const CharT* lhs,
+                         const basic_string_view<CharT,Traits>& rhs)
+    noexcept
+  {
+    return basic_string_view<CharT,Traits>(lhs) <= rhs;
+  }
+
+  template<typename CharT, typename Traits, typename Allocator>
+  inline bool operator<=(const std::basic_string<CharT,Traits,Allocator>& lhs,
+                         const basic_string_view<CharT,Traits>& rhs)
+  {
+    return basic_string_view<CharT,Traits>(lhs) <= rhs;
+  }
+
+  template<typename CharT, typename Traits, typename Allocator>
+  inline bool operator<=(const basic_string_view<CharT,Traits>& lhs,
+                         const std::basic_string<CharT,Traits,Allocator>& rhs)
+  {
+    return lhs <= basic_string_view<CharT,Traits>(rhs);
+  }
+
+  //--------------------------------------------------------------------------
+
+  template<typename CharT, typename Traits>
+  inline bool operator>=(const basic_string_view<CharT,Traits>& lhs,
+                         const basic_string_view<CharT,Traits>& rhs)
+    noexcept
+  {
+    return lhs.compare(rhs) >= 0;
+  }
+
+  template<typename CharT, typename Traits>
+  inline bool operator>=(const basic_string_view<CharT,Traits>& lhs,
+                         const CharT* rhs)
+    noexcept
+  {
+    return lhs >= basic_string_view<CharT,Traits>(rhs);
+  }
+
+  template<typename CharT, typename Traits>
+  inline bool operator>=(const CharT* lhs,
+                         const basic_string_view<CharT,Traits>& rhs)
+    noexcept
+  {
+    return basic_string_view<CharT,Traits>(lhs) >= rhs;
+  }
+
+  template<typename CharT, typename Traits, typename Allocator>
+  inline bool operator>=(const std::basic_string<CharT,Traits,Allocator>& lhs,
+                         const basic_string_view<CharT,Traits>& rhs)
+  {
+    return basic_string_view<CharT,Traits>(lhs) >= rhs;
+  }
+
+  template<typename CharT, typename Traits, typename Allocator>
+  inline bool operator>=(const basic_string_view<CharT,Traits>& lhs,
+                         const std::basic_string<CharT,Traits,Allocator>& rhs)
+  {
+    return lhs >= basic_string_view<CharT,Traits>(rhs);
+  }
+
+} // namespace bpstd
+
+#endif /* BPSTD_DETAIL_STRING_VIEW_INL */
+
+#endif /* BPSTD_STRING_VIEW_HPP */
This page took 0.040675 seconds and 4 git commands to generate.