|  | @@ -87,18 +87,6 @@ struct IntoString<std::string> : std::true_type
 | 
	
		
			
				|  |  |    static std::string into_string(std::string s) { return s; }
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -template <>
 | 
	
		
			
				|  |  | -struct IntoString<string_view> : std::true_type
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -  static std::string into_string(string_view s) { return std::string(s); }
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -template <>
 | 
	
		
			
				|  |  | -struct IntoString<static_string_view> : std::true_type
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -  static string_view into_string(static_string_view s) { return s; }
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  template <>
 | 
	
		
			
				|  |  |  struct IntoString<char> : std::true_type
 | 
	
		
			
				|  |  |  {
 | 
	
	
		
			
				|  | @@ -239,6 +227,25 @@ public:
 | 
	
		
			
				|  |  |    {
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +   * Construct via static_string_view constructor.
 | 
	
		
			
				|  |  | +   * explicit is required to avoid ambiguous overloaded operators (i.e ==,
 | 
	
		
			
				|  |  | +   * etc...) with the ones provided by string_view.
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +  explicit String(static_string_view s)
 | 
	
		
			
				|  |  | +    : String(s, Private())
 | 
	
		
			
				|  |  | +  {
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +   * Construct via string_view constructor.
 | 
	
		
			
				|  |  | +   * explicit is required to avoid ambiguous overloaded operators (i.e ==,
 | 
	
		
			
				|  |  | +   * etc...) with the ones provided by string_view.
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +  explicit String(string_view s)
 | 
	
		
			
				|  |  | +    : String(std::string(s), Private())
 | 
	
		
			
				|  |  | +  {
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    /** Construct via std::string initializer list constructor.  */
 | 
	
		
			
				|  |  |    String(std::initializer_list<char> il)
 | 
	
		
			
				|  |  |      : String(std::string(il))
 | 
	
	
		
			
				|  | @@ -306,6 +313,17 @@ public:
 | 
	
		
			
				|  |  |        This shares ownership of the other string's buffer.  */
 | 
	
		
			
				|  |  |    String& operator=(String const&) noexcept = default;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  String& operator=(static_string_view s)
 | 
	
		
			
				|  |  | +  {
 | 
	
		
			
				|  |  | +    *this = String(s);
 | 
	
		
			
				|  |  | +    return *this;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  String& operator=(string_view s)
 | 
	
		
			
				|  |  | +  {
 | 
	
		
			
				|  |  | +    *this = String(s);
 | 
	
		
			
				|  |  | +    return *this;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    /** Assign from any type implementing the IntoString trait.  */
 | 
	
		
			
				|  |  |    template <typename T>
 | 
	
		
			
				|  |  |    typename // NOLINT(*)
 | 
	
	
		
			
				|  | @@ -328,6 +346,7 @@ public:
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /** Return a view of the string.  */
 | 
	
		
			
				|  |  |    string_view view() const noexcept { return view_; }
 | 
	
		
			
				|  |  | +  operator string_view() const noexcept { return this->view(); }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /** Return true if the instance is an empty stringn or null string.  */
 | 
	
		
			
				|  |  |    bool empty() const noexcept { return view_.empty(); }
 | 
	
	
		
			
				|  | @@ -638,58 +657,155 @@ private:
 | 
	
		
			
				|  |  |    string_view view_;
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -template <typename L, typename R>
 | 
	
		
			
				|  |  | -typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value,
 | 
	
		
			
				|  |  | -                        bool>::type
 | 
	
		
			
				|  |  | -operator==(L&& l, R&& r)
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * Trait for comparable types.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +template <typename T>
 | 
	
		
			
				|  |  | +struct IsComparable : std::false_type
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +template <typename T>
 | 
	
		
			
				|  |  | +struct IsComparable<T&> : IsComparable<T>
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +template <typename T>
 | 
	
		
			
				|  |  | +struct IsComparable<T const> : IsComparable<T>
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +template <typename T>
 | 
	
		
			
				|  |  | +struct IsComparable<T const*> : IsComparable<T*>
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +template <typename T, std::string::size_type N>
 | 
	
		
			
				|  |  | +struct IsComparable<T const[N]> : IsComparable<T[N]>
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +template <>
 | 
	
		
			
				|  |  | +struct IsComparable<char*> : std::true_type
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -  return (AsStringView<L>::view(std::forward<L>(l)) ==
 | 
	
		
			
				|  |  | -          AsStringView<R>::view(std::forward<R>(r)));
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +template <std::string::size_type N>
 | 
	
		
			
				|  |  | +struct IsComparable<char[N]> : std::true_type
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +template <>
 | 
	
		
			
				|  |  | +struct IsComparable<std::string> : std::true_type
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +template <>
 | 
	
		
			
				|  |  | +struct IsComparable<char> : std::true_type
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/** comparison operators */
 | 
	
		
			
				|  |  | +inline bool operator==(const String& l, const String& r)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  return l.view() == r.view();
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +template <typename L>
 | 
	
		
			
				|  |  | +typename std::enable_if<IsComparable<L>::value, bool>::type operator==(
 | 
	
		
			
				|  |  | +  L&& l, const String& r)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  return AsStringView<L>::view(std::forward<L>(l)) == r.view();
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +template <typename R>
 | 
	
		
			
				|  |  | +typename std::enable_if<IsComparable<R>::value, bool>::type operator==(
 | 
	
		
			
				|  |  | +  const String& l, R&& r)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  return l.view() == AsStringView<R>::view(std::forward<R>(r));
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -template <typename L, typename R>
 | 
	
		
			
				|  |  | -typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value,
 | 
	
		
			
				|  |  | -                        bool>::type
 | 
	
		
			
				|  |  | -operator!=(L&& l, R&& r)
 | 
	
		
			
				|  |  | +inline bool operator!=(const String& l, const String& r)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  return l.view() != r.view();
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +template <typename L>
 | 
	
		
			
				|  |  | +typename std::enable_if<IsComparable<L>::value, bool>::type operator!=(
 | 
	
		
			
				|  |  | +  L&& l, const String& r)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -  return (AsStringView<L>::view(std::forward<L>(l)) !=
 | 
	
		
			
				|  |  | -          AsStringView<R>::view(std::forward<R>(r)));
 | 
	
		
			
				|  |  | +  return AsStringView<L>::view(std::forward<L>(l)) != r.view();
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +template <typename R>
 | 
	
		
			
				|  |  | +typename std::enable_if<IsComparable<R>::value, bool>::type operator!=(
 | 
	
		
			
				|  |  | +  const String& l, R&& r)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  return l.view() != AsStringView<R>::view(std::forward<R>(r));
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -template <typename L, typename R>
 | 
	
		
			
				|  |  | -typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value,
 | 
	
		
			
				|  |  | -                        bool>::type
 | 
	
		
			
				|  |  | -operator<(L&& l, R&& r)
 | 
	
		
			
				|  |  | +inline bool operator<(const String& l, const String& r)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -  return (AsStringView<L>::view(std::forward<L>(l)) <
 | 
	
		
			
				|  |  | -          AsStringView<R>::view(std::forward<R>(r)));
 | 
	
		
			
				|  |  | +  return l.view() < r.view();
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +template <typename L>
 | 
	
		
			
				|  |  | +typename std::enable_if<IsComparable<L>::value, bool>::type operator<(
 | 
	
		
			
				|  |  | +  L&& l, const String& r)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  return AsStringView<L>::view(std::forward<L>(l)) < r.view();
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +template <typename R>
 | 
	
		
			
				|  |  | +typename std::enable_if<IsComparable<R>::value, bool>::type operator<(
 | 
	
		
			
				|  |  | +  const String& l, R&& r)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  return l.view() < AsStringView<R>::view(std::forward<R>(r));
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -template <typename L, typename R>
 | 
	
		
			
				|  |  | -typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value,
 | 
	
		
			
				|  |  | -                        bool>::type
 | 
	
		
			
				|  |  | -operator<=(L&& l, R&& r)
 | 
	
		
			
				|  |  | +inline bool operator<=(const String& l, const String& r)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  return l.view() <= r.view();
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +template <typename L>
 | 
	
		
			
				|  |  | +typename std::enable_if<IsComparable<L>::value, bool>::type operator<=(
 | 
	
		
			
				|  |  | +  L&& l, const String& r)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  return AsStringView<L>::view(std::forward<L>(l)) <= r.view();
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +template <typename R>
 | 
	
		
			
				|  |  | +typename std::enable_if<IsComparable<R>::value, bool>::type operator<=(
 | 
	
		
			
				|  |  | +  const String& l, R&& r)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -  return (AsStringView<L>::view(std::forward<L>(l)) <=
 | 
	
		
			
				|  |  | -          AsStringView<R>::view(std::forward<R>(r)));
 | 
	
		
			
				|  |  | +  return l.view() <= AsStringView<R>::view(std::forward<R>(r));
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -template <typename L, typename R>
 | 
	
		
			
				|  |  | -typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value,
 | 
	
		
			
				|  |  | -                        bool>::type
 | 
	
		
			
				|  |  | -operator>(L&& l, R&& r)
 | 
	
		
			
				|  |  | +inline bool operator>(const String& l, const String& r)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  return l.view() > r.view();
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +template <typename L>
 | 
	
		
			
				|  |  | +typename std::enable_if<IsComparable<L>::value, bool>::type operator>(
 | 
	
		
			
				|  |  | +  L&& l, const String& r)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  return AsStringView<L>::view(std::forward<L>(l)) > r.view();
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +template <typename R>
 | 
	
		
			
				|  |  | +typename std::enable_if<IsComparable<R>::value, bool>::type operator>(
 | 
	
		
			
				|  |  | +  const String& l, R&& r)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -  return (AsStringView<L>::view(std::forward<L>(l)) >
 | 
	
		
			
				|  |  | -          AsStringView<R>::view(std::forward<R>(r)));
 | 
	
		
			
				|  |  | +  return l.view() > AsStringView<R>::view(std::forward<R>(r));
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -template <typename L, typename R>
 | 
	
		
			
				|  |  | -typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value,
 | 
	
		
			
				|  |  | -                        bool>::type
 | 
	
		
			
				|  |  | -operator>=(L&& l, R&& r)
 | 
	
		
			
				|  |  | +inline bool operator>=(const String& l, const String& r)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  return l.view() >= r.view();
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +template <typename L>
 | 
	
		
			
				|  |  | +typename std::enable_if<IsComparable<L>::value, bool>::type operator>=(
 | 
	
		
			
				|  |  | +  L&& l, const String& r)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  return AsStringView<L>::view(std::forward<L>(l)) >= r.view();
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +template <typename R>
 | 
	
		
			
				|  |  | +typename std::enable_if<IsComparable<R>::value, bool>::type operator>=(
 | 
	
		
			
				|  |  | +  const String& l, R&& r)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -  return (AsStringView<L>::view(std::forward<L>(l)) >=
 | 
	
		
			
				|  |  | -          AsStringView<R>::view(std::forward<R>(r)));
 | 
	
		
			
				|  |  | +  return l.view() >= AsStringView<R>::view(std::forward<R>(r));
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  std::ostream& operator<<(std::ostream& os, String const& s);
 |