Extend the -Warray-bounds workaround in FixedString.h to gcc-5.
[folly.git] / folly / FixedString.h
index 0f00e6e..935cd82 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -28,6 +28,8 @@
 #include <type_traits>
 #include <utility>
 
+#include <folly/Range.h>
+#include <folly/Utility.h>
 #include <folly/portability/BitsFunctexcept.h>
 #include <folly/portability/Constexpr.h>
 
@@ -72,16 +74,6 @@ constexpr std::size_t FixedStringBase_<Void>::npos;
 
 using FixedStringBase = FixedStringBase_<>;
 
-template <class Char, std::size_t N>
-constexpr std::size_t size(const Char (&)[N]) noexcept {
-  return N - 1u;
-}
-
-template <class Char, std::size_t N>
-constexpr std::size_t size(const BasicFixedString<Char, N>& s) noexcept {
-  return s.size();
-}
-
 // Intentionally NOT constexpr. By making this not constexpr, we make
 // checkOverflow below ill-formed in a constexpr context when the condition
 // it's testing for fails. In this way, precondition violations are reported
@@ -102,19 +94,11 @@ constexpr std::size_t checkOverflowOrNpos(std::size_t i, std::size_t max) {
 }
 
 // Intentionally NOT constexpr. See note above for assertOutOfBounds
-inline void assertOutOfBoundsNothrow() {
-  assert(false && "Array index out of bounds in BasicFixedString");
-}
-
-constexpr std::size_t checkOverflowNothrow(std::size_t i, std::size_t max) {
-  return i <= max ? i : (assertOutOfBoundsNothrow(), i);
-}
-
-// Intentionally NOT constexpr. See note above for assertOutOfBounds
-inline void assertNotNullTerminated() noexcept {
+[[noreturn]] inline void assertNotNullTerminated() noexcept {
   assert(
       false &&
       "Non-null terminated string used to initialize a BasicFixedString");
+  std::terminate(); // Fail hard, fail fast.
 }
 
 // Parsing help for human readers: the following is a constexpr noexcept
@@ -134,6 +118,13 @@ constexpr const Char (&checkNullTerminated(const Char (&a)[N]) noexcept)[N] {
 
 enum class Cmp : int { LT = -1, EQ = 0, GT = 1 };
 
+// Rather annoyingly, GCC's -Warray-bounds warning issues false positives for
+// this code. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61971
+#if defined(__GNUC__) && !defined(__CLANG__) && __GNUC__ <= 5
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
+
 template <class Left, class Right>
 constexpr Cmp compare_(
     const Left& left,
@@ -169,18 +160,21 @@ constexpr bool equal_(
 }
 
 template <class Char, class Left, class Right>
-constexpr Char
-char_at_(const Left& left, const Right& right, std::size_t i) noexcept {
-  return i < fixedstring::size(left)
+constexpr Char char_at_(
+    const Left& left,
+    std::size_t left_count,
+    const Right& right,
+    std::size_t right_count,
+    std::size_t i) noexcept {
+  return i < left_count
       ? left[i]
-      : i < (fixedstring::size(left) + fixedstring::size(right))
-          ? right[i - fixedstring::size(left)]
-          : Char(0);
+      : i < (left_count + right_count) ? right[i - left_count] : Char(0);
 }
 
 template <class Char, class Left, class Right>
 constexpr Char char_at_(
     const Left& left,
+    std::size_t left_size,
     std::size_t left_pos,
     std::size_t left_count,
     const Right& right,
@@ -189,11 +183,10 @@ constexpr Char char_at_(
     std::size_t i) noexcept {
   return i < left_pos
       ? left[i]
-      : (i < right_count + left_pos
-             ? right[i - left_pos + right_pos]
-             : (i < fixedstring::size(left) - left_count + right_count
-                    ? left[i - right_count + left_count]
-                    : Char(0)));
+      : (i < right_count + left_pos ? right[i - left_pos + right_pos]
+                                    : (i < left_size - left_count + right_count
+                                           ? left[i - right_count + left_count]
+                                           : Char(0)));
 }
 
 template <class Left, class Right>
@@ -216,14 +209,14 @@ find_one_of_at_(Char ch, const Right& right, std::size_t pos) noexcept {
 template <class Left, class Right>
 constexpr std::size_t find_(
     const Left& left,
+    std::size_t left_size,
     const Right& right,
     std::size_t pos,
     std::size_t count) noexcept {
-  return find_at_(left, right, pos, count)
-      ? pos
-      : fixedstring::size(left) <= pos + count
+  return find_at_(left, right, pos, count) ? pos
+                                           : left_size <= pos + count
           ? FixedStringBase::npos
-          : find_(left, right, pos + 1u, count);
+          : find_(left, left_size, right, pos + 1u, count);
 }
 
 template <class Left, class Right>
@@ -241,27 +234,27 @@ constexpr std::size_t rfind_(
 template <class Left, class Right>
 constexpr std::size_t find_first_of_(
     const Left& left,
+    std::size_t left_size,
     const Right& right,
     std::size_t pos,
     std::size_t count) noexcept {
-  return find_one_of_at_(left[pos], right, count)
-      ? pos
-      : fixedstring::size(left) <= pos + 1u
+  return find_one_of_at_(left[pos], right, count) ? pos
+                                                  : left_size <= pos + 1u
           ? FixedStringBase::npos
-          : find_first_of_(left, right, pos + 1u, count);
+          : find_first_of_(left, left_size, right, pos + 1u, count);
 }
 
 template <class Left, class Right>
 constexpr std::size_t find_first_not_of_(
     const Left& left,
+    std::size_t left_size,
     const Right& right,
     std::size_t pos,
     std::size_t count) noexcept {
-  return !find_one_of_at_(left[pos], right, count)
-      ? pos
-      : fixedstring::size(left) <= pos + 1u
+  return !find_one_of_at_(left[pos], right, count) ? pos
+                                                   : left_size <= pos + 1u
           ? FixedStringBase::npos
-          : find_first_not_of_(left, right, pos + 1u, count);
+          : find_first_not_of_(left, left_size, right, pos + 1u, count);
 }
 
 template <class Left, class Right>
@@ -292,24 +285,44 @@ struct Helper {
   template <class Char, class Left, class Right, std::size_t... Is>
   static constexpr BasicFixedString<Char, sizeof...(Is)> concat_(
       const Left& left,
+      std::size_t left_count,
       const Right& right,
-      std::index_sequence<Is...> is) noexcept {
-    return {left, right, is};
+      std::size_t right_count,
+      folly::index_sequence<Is...> is) noexcept {
+    return {left, left_count, right, right_count, is};
   }
 
   template <class Char, class Left, class Right, std::size_t... Is>
   static constexpr BasicFixedString<Char, sizeof...(Is)> replace_(
       const Left& left,
+      std::size_t left_size,
       std::size_t left_pos,
       std::size_t left_count,
       const Right& right,
       std::size_t right_pos,
       std::size_t right_count,
-      std::index_sequence<Is...> is) noexcept {
-    return {left, left_pos, left_count, right, right_pos, right_count, is};
+      folly::index_sequence<Is...> is) noexcept {
+    return {left,
+            left_size,
+            left_pos,
+            left_count,
+            right,
+            right_pos,
+            right_count,
+            is};
+  }
+
+  template <class Char, std::size_t N>
+  static constexpr const Char (
+      &data_(const BasicFixedString<Char, N>& that) noexcept)[N + 1u] {
+    return that.data_;
   }
 };
 
+#if defined(__GNUC__) && !defined(__CLANG__) && __GNUC__ <= 4
+#pragma GCC diagnostic pop
+#endif
+
 template <class T>
 FOLLY_CPP14_CONSTEXPR void constexpr_swap(T& a, T& b) noexcept(
     noexcept(a = T(std::move(a)))) {
@@ -424,10 +437,6 @@ struct ReverseIterator {
 } // namespace fixedstring
 } // namespace detail
 
-// Defined in folly/Range.h
-template <class Iter>
-class Range;
-
 // Defined in folly/Hash.h
 std::uint32_t hsieh_hash32_buf(const void* buf, std::size_t len);
 
@@ -491,7 +500,7 @@ std::uint32_t hsieh_hash32_buf(const void* buf, std::size_t len);
  * of types `FixedString<4>`, `FixedString<8>`, etc. For example:
  * \par
  * \code
- * using namespace folly::StringLiterals;
+ * using namespace folly::string_literals;
  * constexpr auto hello = "hello"_fs8; // A FixedString<8> containing "hello"
  * \endcode
  * \par
@@ -503,7 +512,7 @@ std::uint32_t hsieh_hash32_buf(const void* buf, std::size_t len);
  * the right size. For example:
  * \par
  * \code
- * using namespace folly::StringLiterals;
+ * using namespace folly::string_literals;
  * // NOTE: Only works on compilers with GNU extensions enabled. Clang and
  * // gcc support this (-Wgnu-string-literal-operator-template):
  * constexpr auto hello = "hello"_fs; // A FixedString<5> containing "hello"
@@ -539,13 +548,13 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
   Char data_[N + 1u]; // +1 for the null terminator
   std::size_t size_; // Nbr of chars, not incl. null terminator. size_ <= N.
 
-  using Indices = std::make_index_sequence<N>;
+  using Indices = folly::make_index_sequence<N>;
 
   template <class That, std::size_t... Is>
   constexpr BasicFixedString(
       const That& that,
       std::size_t size,
-      std::index_sequence<Is...>,
+      folly::index_sequence<Is...>,
       std::size_t pos = 0,
       std::size_t count = npos) noexcept
       : data_{(Is < (size - pos) && Is < count ? that[Is + pos] : Char(0))...,
@@ -556,31 +565,40 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
   constexpr BasicFixedString(
       std::size_t count,
       Char ch,
-      std::index_sequence<Is...>) noexcept
+      folly::index_sequence<Is...>) noexcept
       : data_{((Is < count) ? ch : Char(0))..., Char(0)}, size_{count} {}
 
   // Concatenation constructor
   template <class Left, class Right, std::size_t... Is>
   constexpr BasicFixedString(
       const Left& left,
+      std::size_t left_size,
       const Right& right,
-      std::index_sequence<Is...>) noexcept
-      : data_{detail::fixedstring::char_at_<Char>(left, right, Is)..., Char(0)},
-        size_{detail::fixedstring::size(left) +
-              detail::fixedstring::size(right)} {}
+      std::size_t right_size,
+      folly::index_sequence<Is...>) noexcept
+      : data_{detail::fixedstring::char_at_<Char>(
+                  left,
+                  left_size,
+                  right,
+                  right_size,
+                  Is)...,
+              Char(0)},
+        size_{left_size + right_size} {}
 
   // Replace constructor
   template <class Left, class Right, std::size_t... Is>
   constexpr BasicFixedString(
       const Left& left,
+      std::size_t left_size,
       std::size_t left_pos,
       std::size_t left_count,
       const Right& right,
       std::size_t right_pos,
       std::size_t right_count,
-      std::index_sequence<Is...>) noexcept
+      folly::index_sequence<Is...>) noexcept
       : data_{detail::fixedstring::char_at_<Char>(
                   left,
+                  left_size,
                   left_pos,
                   left_count,
                   right,
@@ -588,7 +606,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
                   right_count,
                   Is)...,
               Char(0)},
-        size_{detail::fixedstring::size(left) - left_count + right_count} {}
+        size_{left_size - left_count + right_count} {}
 
  public:
   using size_type = std::size_t;
@@ -666,7 +684,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       : BasicFixedString{
             that.data_,
             that.size_,
-            std::make_index_sequence<(M < N ? M : N)>{},
+            folly::make_index_sequence<(M < N ? M : N)>{},
             pos,
             detail::fixedstring::checkOverflow(
                 detail::fixedstring::checkOverflowOrNpos(
@@ -687,7 +705,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
   constexpr /* implicit */ BasicFixedString(const Char (&that)[M]) noexcept
       : BasicFixedString{detail::fixedstring::checkNullTerminated(that),
                          M - 1u,
-                         std::make_index_sequence<M - 1u>{}} {}
+                         folly::make_index_sequence<M - 1u>{}} {}
 
   /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
    * Construct from a `const Char*` and count
@@ -1153,7 +1171,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
 #ifdef NDEBUG
     return data_[i];
 #else
-    return data_[detail::fixedstring::checkOverflowNothrow(i, size_)];
+    return data_[detail::fixedstring::checkOverflow(i, size_)];
 #endif
   }
 
@@ -1164,21 +1182,21 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
 #ifdef NDEBUG
     return data_[i];
 #else
-    return data_[detail::fixedstring::checkOverflowNothrow(i, size_)];
+    return data_[detail::fixedstring::checkOverflow(i, size_)];
 #endif
   }
 
   /**
    * \note Equivalent to `(*this)[0]`
    */
-  FOLLY_CPP14_CONSTEXPR Char& front() noexcept(false) {
+  FOLLY_CPP14_CONSTEXPR Char& front() noexcept {
     return (*this)[0u];
   }
 
   /**
    * \overload
    */
-  constexpr const Char& front() const noexcept(false) {
+  constexpr const Char& front() const noexcept {
     return (*this)[0u];
   }
 
@@ -1186,22 +1204,22 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
    * \note Equivalent to `at(size()-1)`
    * \pre `!empty()`
    */
-  FOLLY_CPP14_CONSTEXPR Char& back() noexcept(false) {
+  FOLLY_CPP14_CONSTEXPR Char& back() noexcept {
 #ifdef NDEBUG
     return data_[size_ - 1u];
 #else
-    return data_[size_ - detail::fixedstring::checkOverflowNothrow(1u, size_)];
+    return data_[size_ - detail::fixedstring::checkOverflow(1u, size_)];
 #endif
   }
 
   /**
    * \overload
    */
-  constexpr const Char& back() const noexcept(false) {
+  constexpr const Char& back() const noexcept {
 #ifdef NDEBUG
     return data_[size_ - 1u];
 #else
-    return data_[size_ - detail::fixedstring::checkOverflowNothrow(1u, size_)];
+    return data_[size_ - detail::fixedstring::checkOverflow(1u, size_)];
 #endif
   }
 
@@ -1315,7 +1333,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     count = detail::fixedstring::checkOverflowOrNpos(count, that.size_ - pos);
     detail::fixedstring::checkOverflow(count, N - size_);
     for (std::size_t i = 0u; i < count; ++i)
-      data_[size_ + i] = that[pos + i];
+      data_[size_ + i] = that.data_[pos + i];
     size_ += count;
     data_[size_] = Char(0);
     return *this;
@@ -1567,11 +1585,11 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       std::size_t that_pos,
       std::size_t that_count) const noexcept(false) {
     return static_cast<int>(detail::fixedstring::compare_(
-        *this,
+        data_,
         detail::fixedstring::checkOverflow(this_pos, size_),
         detail::fixedstring::checkOverflow(this_count, size_ - this_pos) +
             this_pos,
-        that,
+        that.data_,
         detail::fixedstring::checkOverflow(that_pos, that.size_),
         detail::fixedstring::checkOverflow(that_count, that.size_ - that_pos) +
             that_pos));
@@ -1585,6 +1603,13 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return compare(0u, size_, that, folly::constexpr_strlen(that));
   }
 
+  /**
+   * \overload
+   */
+  constexpr int compare(Range<const Char*> that) const noexcept {
+    return compare(0u, size_, that.begin(), that.size());
+  }
+
   /**
    * Compare two strings for lexicographical ordering.
    * \note Equivalent to
@@ -1597,6 +1622,16 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return compare(this_pos, this_count, that, folly::constexpr_strlen(that));
   }
 
+  /**
+   * \overload
+   */
+  constexpr int compare(
+      std::size_t this_pos,
+      std::size_t this_count,
+      Range<const Char*> that) const noexcept(false) {
+    return compare(this_pos, this_count, that.begin(), that.size());
+  }
+
   /**
    * Compare two strings for lexicographical ordering.
    *
@@ -1618,7 +1653,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       const Char* that,
       std::size_t that_count) const noexcept(false) {
     return static_cast<int>(detail::fixedstring::compare_(
-        *this,
+        data_,
         detail::fixedstring::checkOverflow(this_pos, size_),
         detail::fixedstring::checkOverflowOrNpos(this_count, size_ - this_pos) +
             this_pos,
@@ -1627,6 +1662,18 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
         that_count));
   }
 
+  constexpr int compare(
+      std::size_t this_pos,
+      std::size_t this_count,
+      Range<const Char*> that,
+      std::size_t that_count) const noexcept(false) {
+    return compare(
+        this_pos,
+        this_count,
+        that.begin(),
+        detail::fixedstring::checkOverflow(that_count, that.size()));
+  }
+
   /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
    * Return a substring from `pos` to the end of the string.
    * \note Equivalent to `BasicFixedString{*this, pos}`
@@ -1747,7 +1794,8 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       const Char* that,
       std::size_t that_count) noexcept(false) {
     return *this = detail::fixedstring::Helper::replace_<Char>(
-               *this,
+               data_,
+               size_,
                detail::fixedstring::checkOverflow(this_pos, size_),
                detail::fixedstring::checkOverflowOrNpos(
                    this_count, size_ - this_pos),
@@ -1855,14 +1903,15 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       std::size_t that_pos,
       std::size_t that_count) const noexcept(false) {
     return detail::fixedstring::Helper::replace_<Char>(
-        *this,
+        data_,
+        size_,
         detail::fixedstring::checkOverflow(this_pos, size_),
         detail::fixedstring::checkOverflowOrNpos(this_count, size_ - this_pos),
-        that,
+        that.data_,
         detail::fixedstring::checkOverflow(that_pos, that.size_),
         detail::fixedstring::checkOverflowOrNpos(
             that_count, that.size_ - that_pos),
-        std::make_index_sequence<N + M>{});
+        folly::make_index_sequence<N + M>{});
   }
 
   /**
@@ -1955,13 +2004,14 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       std::size_t that_pos,
       std::size_t that_count) const noexcept(false) {
     return detail::fixedstring::Helper::replace_<Char>(
-        *this,
+        data_,
+        size_,
         detail::fixedstring::checkOverflow(this_pos, size_),
         detail::fixedstring::checkOverflowOrNpos(this_count, size_ - this_pos),
         detail::fixedstring::checkNullTerminated(that),
         detail::fixedstring::checkOverflow(that_pos, M - 1u),
         detail::fixedstring::checkOverflowOrNpos(that_count, M - 1u - that_pos),
-        std::make_index_sequence<N + M - 1u>{});
+        folly::make_index_sequence<N + M - 1u>{});
   }
 
   /**
@@ -2075,7 +2125,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       const BasicFixedString<Char, M>& that,
       std::size_t pos) const noexcept(false) {
     return that.size_ <= size_ - detail::fixedstring::checkOverflow(pos, size_)
-        ? detail::fixedstring::find_(*this, that, pos, that.size_)
+        ? detail::fixedstring::find_(data_, size_, that.data_, pos, that.size_)
         : npos;
   }
 
@@ -2114,7 +2164,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       std::size_t pos,
       std::size_t count) const noexcept(false) {
     return count <= size_ - detail::fixedstring::checkOverflow(pos, size_)
-        ? detail::fixedstring::find_(*this, that, pos, count)
+        ? detail::fixedstring::find_(data_, size_, that, pos, count)
         : npos;
   }
 
@@ -2136,7 +2186,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     using A = const Char[1u];
     return 0u == size_ - detail::fixedstring::checkOverflow(pos, size_)
         ? npos
-        : detail::fixedstring::find_(*this, A{ch}, pos, 1u);
+        : detail::fixedstring::find_(data_, size_, A{ch}, pos, 1u);
   }
 
   /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
@@ -2161,8 +2211,8 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       std::size_t pos) const noexcept(false) {
     return that.size_ <= size_
         ? detail::fixedstring::rfind_(
-              *this,
-              that,
+              data_,
+              that.data_,
               folly::constexpr_min(
                   detail::fixedstring::checkOverflow(pos, size_),
                   size_ - that.size_),
@@ -2206,7 +2256,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       std::size_t count) const noexcept(false) {
     return count <= size_
         ? detail::fixedstring::rfind_(
-              *this,
+              data_,
               that,
               folly::constexpr_min(
                   detail::fixedstring::checkOverflow(pos, size_),
@@ -2234,7 +2284,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return 0u == size_
         ? npos
         : detail::fixedstring::rfind_(
-              *this,
+              data_,
               A{ch},
               folly::constexpr_min(
                   detail::fixedstring::checkOverflow(pos, size_), size_ - 1u),
@@ -2262,7 +2312,8 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       std::size_t pos) const noexcept(false) {
     return size_ == detail::fixedstring::checkOverflow(pos, size_)
         ? npos
-        : detail::fixedstring::find_first_of_(*this, that, pos, that.size_);
+        : detail::fixedstring::find_first_of_(
+              data_, size_, that.data_, pos, that.size_);
   }
 
   /**
@@ -2303,7 +2354,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       std::size_t count) const noexcept(false) {
     return size_ == detail::fixedstring::checkOverflow(pos, size_)
         ? npos
-        : detail::fixedstring::find_first_of_(*this, that, pos, count);
+        : detail::fixedstring::find_first_of_(data_, size_, that, pos, count);
   }
 
   /**
@@ -2324,7 +2375,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     using A = const Char[1u];
     return size_ == detail::fixedstring::checkOverflow(pos, size_)
         ? npos
-        : detail::fixedstring::find_first_of_(*this, A{ch}, pos, 1u);
+        : detail::fixedstring::find_first_of_(data_, size_, A{ch}, pos, 1u);
   }
 
   /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
@@ -2347,7 +2398,8 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       std::size_t pos) const noexcept(false) {
     return size_ == detail::fixedstring::checkOverflow(pos, size_)
         ? npos
-        : detail::fixedstring::find_first_not_of_(*this, that, pos, that.size_);
+        : detail::fixedstring::find_first_not_of_(
+              data_, size_, that.data_, pos, that.size_);
   }
 
   /**
@@ -2388,7 +2440,8 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       std::size_t count) const noexcept(false) {
     return size_ == detail::fixedstring::checkOverflow(pos, size_)
         ? npos
-        : detail::fixedstring::find_first_not_of_(*this, that, pos, count);
+        : detail::fixedstring::find_first_not_of_(
+              data_, size_, that, pos, count);
   }
 
   /**
@@ -2408,7 +2461,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       noexcept(false) {
     using A = const Char[1u];
     return 1u <= size_ - detail::fixedstring::checkOverflow(pos, size_)
-        ? detail::fixedstring::find_first_not_of_(*this, A{ch}, pos, 1u)
+        ? detail::fixedstring::find_first_not_of_(data_, size_, A{ch}, pos, 1u)
         : npos;
   }
 
@@ -2434,8 +2487,8 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return 0u == size_
         ? npos
         : detail::fixedstring::find_last_of_(
-              *this,
-              that,
+              data_,
+              that.data_,
               folly::constexpr_min(
                   detail::fixedstring::checkOverflow(pos, size_), size_ - 1u),
               that.size_);
@@ -2480,7 +2533,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return 0u == size_
         ? npos
         : detail::fixedstring::find_last_of_(
-              *this,
+              data_,
               that,
               folly::constexpr_min(
                   detail::fixedstring::checkOverflow(pos, size_), size_ - 1u),
@@ -2506,7 +2559,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return 0u == size_
         ? npos
         : detail::fixedstring::find_last_of_(
-              *this,
+              data_,
               A{ch},
               folly::constexpr_min(
                   detail::fixedstring::checkOverflow(pos, size_), size_ - 1u),
@@ -2535,8 +2588,8 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return 0u == size_
         ? npos
         : detail::fixedstring::find_last_not_of_(
-              *this,
-              that,
+              data_,
+              that.data_,
               folly::constexpr_min(
                   detail::fixedstring::checkOverflow(pos, size_), size_ - 1u),
               that.size_);
@@ -2581,7 +2634,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return 0u == size_
         ? npos
         : detail::fixedstring::find_last_not_of_(
-              *this,
+              data_,
               that,
               folly::constexpr_min(
                   detail::fixedstring::checkOverflow(pos, size_), size_ - 1u),
@@ -2607,7 +2660,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return 0u == size_
         ? npos
         : detail::fixedstring::find_last_not_of_(
-              *this,
+              data_,
               A{ch},
               folly::constexpr_min(
                   detail::fixedstring::checkOverflow(pos, size_), size_ - 1u),
@@ -2621,7 +2674,7 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       const Char* a,
       const BasicFixedString& b) noexcept {
     return detail::fixedstring::equal_(
-        a, folly::constexpr_strlen(a), b, b.size());
+        a, folly::constexpr_strlen(a), b.data_, b.size_);
   }
 
   /**
@@ -2633,6 +2686,24 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return b == a;
   }
 
+  /**
+   * \overload
+   */
+  friend constexpr bool operator==(
+      Range<const Char*> a,
+      const BasicFixedString& b) noexcept {
+    return detail::fixedstring::equal_(a.begin(), a.size(), b.data_, b.size_);
+  }
+
+  /**
+   * \overload
+   */
+  friend constexpr bool operator==(
+      const BasicFixedString& a,
+      Range<const Char*> b) noexcept {
+    return b == a;
+  }
+
   friend constexpr bool operator!=(
       const Char* a,
       const BasicFixedString& b) noexcept {
@@ -2648,12 +2719,30 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return !(b == a);
   }
 
+  /**
+   * \overload
+   */
+  friend constexpr bool operator!=(
+      Range<const Char*> a,
+      const BasicFixedString& b) noexcept {
+    return !(a == b);
+  }
+
+  /**
+   * \overload
+   */
+  friend constexpr bool operator!=(
+      const BasicFixedString& a,
+      Range<const Char*> b) noexcept {
+    return !(a == b);
+  }
+
   friend constexpr bool operator<(
       const Char* a,
       const BasicFixedString& b) noexcept {
     return detail::fixedstring::Cmp::LT ==
         detail::fixedstring::compare_(
-               a, 0u, folly::constexpr_strlen(a), b, 0u, b.size_);
+               a, 0u, folly::constexpr_strlen(a), b.data_, 0u, b.size_);
   }
 
   /**
@@ -2664,7 +2753,29 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       const Char* b) noexcept {
     return detail::fixedstring::Cmp::LT ==
         detail::fixedstring::compare_(
-               a, 0u, a.size_, b, 0u, folly::constexpr_strlen(b));
+               a.data_, 0u, a.size_, b, 0u, folly::constexpr_strlen(b));
+  }
+
+  /**
+   * \overload
+   */
+  friend constexpr bool operator<(
+      Range<const Char*> a,
+      const BasicFixedString& b) noexcept {
+    return detail::fixedstring::Cmp::LT ==
+        detail::fixedstring::compare_(
+               a.begin(), 0u, a.size(), b.data_, 0u, b.size_);
+  }
+
+  /**
+   * \overload
+   */
+  friend constexpr bool operator<(
+      const BasicFixedString& a,
+      Range<const Char*> b) noexcept {
+    return detail::fixedstring::Cmp::LT ==
+        detail::fixedstring::compare_(
+               a.data_, 0u, a.size_, b.begin(), 0u, b.size());
   }
 
   friend constexpr bool operator>(
@@ -2682,6 +2793,24 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return b < a;
   }
 
+  /**
+   * \overload
+   */
+  friend constexpr bool operator>(
+      Range<const Char*> a,
+      const BasicFixedString& b) noexcept {
+    return b < a;
+  }
+
+  /**
+   * \overload
+   */
+  friend constexpr bool operator>(
+      const BasicFixedString& a,
+      Range<const Char*> b) noexcept {
+    return b < a;
+  }
+
   friend constexpr bool operator<=(
       const Char* a,
       const BasicFixedString& b) noexcept {
@@ -2697,6 +2826,24 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return !(b < a);
   }
 
+  /**
+   * \overload
+   */
+  friend constexpr bool operator<=(
+      Range<const Char*> const& a,
+      const BasicFixedString& b) noexcept {
+    return !(b < a);
+  }
+
+  /**
+   * \overload
+   */
+  friend constexpr bool operator<=(
+      const BasicFixedString& a,
+      Range<const Char*> b) noexcept {
+    return !(b < a);
+  }
+
   friend constexpr bool operator>=(
       const Char* a,
       const BasicFixedString& b) noexcept {
@@ -2712,6 +2859,24 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
     return !(a < b);
   }
 
+  /**
+   * \overload
+   */
+  friend constexpr bool operator>=(
+      Range<const Char*> a,
+      const BasicFixedString& b) noexcept {
+    return !(a < b);
+  }
+
+  /**
+   * \overload
+   */
+  friend constexpr bool operator>=(
+      const BasicFixedString& a,
+      Range<const Char*> const& b) noexcept {
+    return !(a < b);
+  }
+
   /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
    * Asymmetric concatenation
    */
@@ -2721,8 +2886,10 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       const BasicFixedString& b) noexcept {
     return detail::fixedstring::Helper::concat_<Char>(
         detail::fixedstring::checkNullTerminated(a),
-        b,
-        std::make_index_sequence<N + M - 1u>{});
+        M - 1u,
+        b.data_,
+        b.size_,
+        folly::make_index_sequence<N + M - 1u>{});
   }
 
   /**
@@ -2733,9 +2900,11 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       const BasicFixedString& a,
       const Char (&b)[M]) noexcept {
     return detail::fixedstring::Helper::concat_<Char>(
-        a,
+        a.data_,
+        a.size_,
         detail::fixedstring::checkNullTerminated(b),
-        std::make_index_sequence<N + M - 1u>{});
+        M - 1u,
+        folly::make_index_sequence<N + M - 1u>{});
   }
 
   /**
@@ -2746,7 +2915,11 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       const BasicFixedString& b) noexcept {
     using A = const Char[2u];
     return detail::fixedstring::Helper::concat_<Char>(
-        A{a, Char(0)}, b, std::make_index_sequence<N + 1u>{});
+        A{a, Char(0)},
+        1u,
+        b.data_,
+        b.size_,
+        folly::make_index_sequence<N + 1u>{});
   }
 
   /**
@@ -2757,7 +2930,11 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
       Char b) noexcept {
     using A = const Char[2u];
     return detail::fixedstring::Helper::concat_<Char>(
-        a, A{b, Char(0)}, std::make_index_sequence<N + 1u>{});
+        a.data_,
+        a.size_,
+        A{b, Char(0)},
+        1u,
+        folly::make_index_sequence<N + 1u>{});
   }
 };
 
@@ -2768,7 +2945,11 @@ template <class Char, std::size_t A, std::size_t B>
 constexpr bool operator==(
     const BasicFixedString<Char, A>& a,
     const BasicFixedString<Char, B>& b) noexcept {
-  return detail::fixedstring::equal_(a, a.size(), b, b.size());
+  return detail::fixedstring::equal_(
+      detail::fixedstring::Helper::data_(a),
+      a.size(),
+      detail::fixedstring::Helper::data_(b),
+      b.size());
 }
 
 template <class Char, std::size_t A, std::size_t B>
@@ -2783,7 +2964,13 @@ constexpr bool operator<(
     const BasicFixedString<Char, A>& a,
     const BasicFixedString<Char, B>& b) noexcept {
   return detail::fixedstring::Cmp::LT ==
-      detail::fixedstring::compare_(a, 0u, a.size(), b, 0u, b.size());
+      detail::fixedstring::compare_(
+             detail::fixedstring::Helper::data_(a),
+             0u,
+             a.size(),
+             detail::fixedstring::Helper::data_(b),
+             0u,
+             b.size());
 }
 
 template <class Char, std::size_t A, std::size_t B>
@@ -2815,7 +3002,11 @@ constexpr BasicFixedString<Char, N + M> operator+(
     const BasicFixedString<Char, N>& a,
     const BasicFixedString<Char, M>& b) noexcept {
   return detail::fixedstring::Helper::concat_<Char>(
-      a, b, std::make_index_sequence<N + M>{});
+      detail::fixedstring::Helper::data_(a),
+      a.size(),
+      detail::fixedstring::Helper::data_(b),
+      b.size(),
+      folly::make_index_sequence<N + M>{});
 }
 
 /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
@@ -2842,8 +3033,8 @@ FOLLY_CPP14_CONSTEXPR void swap(
   a.swap(b);
 }
 
-inline namespace Literals {
-inline namespace StringLiterals {
+inline namespace literals {
+inline namespace string_literals {
 inline namespace {
 // "const std::size_t&" is so that folly::npos has the same address in every
 // translation unit. This is to avoid potential violations of the ODR.
@@ -2862,7 +3053,7 @@ constexpr const std::size_t& npos = detail::fixedstring::FixedStringBase::npos;
  * \par Example:
  * \par
  * \code
- * using namespace folly::StringLiterals;
+ * using namespace folly::string_literals;
  * constexpr auto hello = "hello world!"_fs;
  * \endcode
  *