• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3 // Copyright (c) 2019-2020 Krystian Stasiowski (sdkrystian at gmail dot com)
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // Official repository: https://github.com/boostorg/static_string
9 //
10 
11 #ifndef BOOST_STATIC_STRING_STATIC_STRING_HPP
12 #define BOOST_STATIC_STRING_STATIC_STRING_HPP
13 
14 // External include guard
15 #ifndef BOOST_STATIC_STRING_CONFIG_HPP
16 #include <boost/static_string/config.hpp>
17 #endif
18 
19 #include <algorithm>
20 #include <cstdint>
21 #include <cstdio>
22 #include <cwchar>
23 #include <functional>
24 #include <initializer_list>
25 #include <iosfwd>
26 #include <type_traits>
27 
28 namespace boost {
29 namespace static_strings {
30 
31 #ifndef BOOST_STATIC_STRING_DOCS
32 template<std::size_t N, typename CharT, typename Traits>
33 class basic_static_string;
34 
35 //------------------------------------------------------------------------------
36 //
37 // Aliases
38 //
39 //------------------------------------------------------------------------------
40 
41 template<std::size_t N>
42 using static_string =
43   basic_static_string<N, char, std::char_traits<char>>;
44 
45 template<std::size_t N>
46 using static_wstring =
47   basic_static_string<N, wchar_t, std::char_traits<wchar_t>>;
48 
49 template<std::size_t N>
50 using static_u16string =
51   basic_static_string<N, char16_t, std::char_traits<char16_t>>;
52 
53 template<std::size_t N>
54 using static_u32string =
55   basic_static_string<N, char32_t, std::char_traits<char32_t>>;
56 
57 #ifdef BOOST_STATIC_STRING_CPP20
58 template<std::size_t N>
59 using static_u8string =
60   basic_static_string<N, char8_t, std::char_traits<char8_t>>;
61 #endif
62 
63 //--------------------------------------------------------------------------
64 //
65 // Detail
66 //
67 //--------------------------------------------------------------------------
68 
69 namespace detail {
70 
71 // Find the smallest width integral type that can hold a value as large as N (Glen Fernandes)
72 template<std::size_t N>
73 using smallest_width =
74   typename std::conditional<(N <= (std::numeric_limits<unsigned char>::max)()), unsigned char,
75   typename std::conditional<(N <= (std::numeric_limits<unsigned short>::max)()), unsigned short,
76   typename std::conditional<(N <= (std::numeric_limits<unsigned int>::max)()), unsigned int,
77   typename std::conditional<(N <= (std::numeric_limits<unsigned long>::max)()), unsigned long,
78   typename std::conditional<(N <= (std::numeric_limits<unsigned long long>::max)()), unsigned long long,
79   std::size_t>::type>::type>::type>::type>::type;
80 
81 // std::is_nothrow_convertible is C++20
82 template<typename To>
83 void is_nothrow_convertible_helper(To) noexcept;
84 
85 // MSVC is unable to parse this as a single expression, so a helper is needed
86 template<typename From, typename To, typename =
87   decltype(is_nothrow_convertible_helper<To>(std::declval<From>()))>
88 struct is_nothrow_convertible_msvc_helper
89 {
90   static const bool value =
91     noexcept(is_nothrow_convertible_helper<To>(std::declval<From>()));
92 };
93 
94 template<typename From, typename To, typename = void>
95 struct is_nothrow_convertible
96   : std::false_type { };
97 
98 template<typename From, typename To>
99 struct is_nothrow_convertible<From, To, typename std::enable_if<
100   is_nothrow_convertible_msvc_helper<From, To>::value>::type>
101     : std::true_type { };
102 
103 // GCC 4.8, 4.9 workaround for void_t to make the defining-type-id dependant
104 template<typename...>
105 struct void_t_helper
106 {
107   using type = void;
108 };
109 
110 // void_t for c++11
111 template<typename... Ts>
112 using void_t = typename void_t_helper<Ts...>::type;
113 
114 // Check if a type can be used for templated
115 // overloads string_view_type
116 template<typename T, typename CharT, typename Traits, typename = void>
117 struct enable_if_viewable { };
118 
119 template<typename T, typename CharT, typename Traits>
120 struct enable_if_viewable<T, CharT, Traits,
121   typename std::enable_if<
122     std::is_convertible<const T&, basic_string_view<CharT, Traits>>::value &&
123       !std::is_convertible<const T&, const CharT*>::value>::type>
124 {
125   using type = void;
126 };
127 
128 template<typename T, typename CharT, typename Traits>
129 using enable_if_viewable_t = typename enable_if_viewable<T, CharT, Traits>::type;
130 
131 // Simplified check for if a type is an iterator
132 template<typename T, typename = void>
133 struct is_iterator : std::false_type { };
134 
135 template<typename T>
136 struct is_iterator<T,
137   typename std::enable_if<std::is_class<T>::value,
138     void_t<typename T::iterator_category>>::type>
139       : std::true_type { };
140 
141 template<typename T>
142 struct is_iterator<T*, void>
143   : std::true_type { };
144 
145 template<typename T, typename = void>
146 struct is_input_iterator : std::false_type { };
147 
148 template<typename T>
149 struct is_input_iterator<T, typename std::enable_if<is_iterator<T>::value &&
150   std::is_convertible<typename std::iterator_traits<T>::iterator_category,
151     std::input_iterator_tag>::value>::type>
152       : std::true_type { };
153 
154 template<typename T, typename = void>
155 struct is_forward_iterator : std::false_type { };
156 
157 template<typename T>
158 struct is_forward_iterator<T, typename std::enable_if<is_iterator<T>::value &&
159   std::is_convertible<typename std::iterator_traits<T>::iterator_category,
160     std::forward_iterator_tag>::value>::type>
161       : std::true_type { };
162 
163 template<typename T, typename = void>
164 struct is_subtractable
165   : std::false_type { };
166 
167 template<typename T>
168 struct is_subtractable<T, void_t<decltype(std::declval<T&>() - std::declval<T&>())>>
169   : std::true_type { };
170 
171 // constexpr distance for c++14
172 template<
173   typename ForwardIt,
174   typename std::enable_if<!is_subtractable<ForwardIt>::value>::type* = nullptr>
175 BOOST_STATIC_STRING_CPP14_CONSTEXPR
176 std::size_t
distance(ForwardIt first,ForwardIt last)177 distance(ForwardIt first, ForwardIt last)
178 {
179   std::size_t dist = 0;
180   for (; first != last; ++first, ++dist);
181   return dist;
182 }
183 
184 template<
185   typename RandomIt,
186   typename std::enable_if<is_subtractable<RandomIt>::value>::type* = nullptr>
187 BOOST_STATIC_STRING_CPP14_CONSTEXPR
188 std::size_t
distance(RandomIt first,RandomIt last)189 distance(RandomIt first, RandomIt last)
190 {
191   return last - first;
192 }
193 
194 // Copy using traits, respecting iterator rules
195 template<typename Traits, typename InputIt, typename CharT>
196 BOOST_STATIC_STRING_CPP14_CONSTEXPR
197 void
copy_with_traits(InputIt first,InputIt last,CharT * out)198 copy_with_traits(
199   InputIt first,
200   InputIt last,
201   CharT* out)
202 {
203   for (; first != last; ++first, ++out)
204     Traits::assign(*out, *first);
205 }
206 
207 // Optimization for using the smallest possible type
208 template<std::size_t N, typename CharT, typename Traits>
209 class static_string_base
210 {
211 private:
212   using size_type = smallest_width<N>;
213   using value_type = typename Traits::char_type;
214   using pointer = value_type*;
215   using const_pointer = const value_type*;
216 public:
217   BOOST_STATIC_STRING_CPP11_CONSTEXPR
static_string_base()218   static_string_base() noexcept { };
219 
220   BOOST_STATIC_STRING_CPP14_CONSTEXPR
221   pointer
data_impl()222   data_impl() noexcept
223   {
224     return data_;
225   }
226 
227   BOOST_STATIC_STRING_CPP14_CONSTEXPR
228   const_pointer
data_impl() const229   data_impl() const noexcept
230   {
231     return data_;
232   }
233 
234   BOOST_STATIC_STRING_CPP11_CONSTEXPR
235   std::size_t
size_impl() const236   size_impl() const noexcept
237   {
238     return size_;
239   }
240 
241   BOOST_STATIC_STRING_CPP14_CONSTEXPR
242   std::size_t
set_size(std::size_t n)243   set_size(std::size_t n) noexcept
244   {
245     // Functions that set size will throw
246     // if the new size would exceed max_size()
247     // therefore we can guarantee that this will
248     // not lose data.
249     return size_ = size_type(n);
250   }
251 
252   BOOST_STATIC_STRING_CPP14_CONSTEXPR
253   void
term_impl()254   term_impl() noexcept
255   {
256     Traits::assign(data_[size_], value_type());
257   }
258 
259   size_type size_ = 0;
260 #ifdef BOOST_STATIC_STRING_CPP20
261   value_type data_[N + 1];
262 #else
263   value_type data_[N + 1]{};
264 #endif
265 };
266 
267 // Optimization for when the size is 0
268 template<typename CharT, typename Traits>
269 class static_string_base<0, CharT, Traits>
270 {
271 private:
272   using value_type = typename Traits::char_type;
273   using pointer = value_type*;
274 public:
275   BOOST_STATIC_STRING_CPP11_CONSTEXPR
static_string_base()276   static_string_base() noexcept { }
277 
278   // Modifying the null terminator is UB
279   BOOST_STATIC_STRING_CPP11_CONSTEXPR
280   pointer
data_impl() const281   data_impl() const noexcept
282   {
283     return const_cast<pointer>(&null_);
284   }
285 
286   BOOST_STATIC_STRING_CPP11_CONSTEXPR
287   std::size_t
size_impl() const288   size_impl() const noexcept
289   {
290     return 0;
291   }
292 
293   BOOST_STATIC_STRING_CPP11_CONSTEXPR
294   std::size_t
set_size(std::size_t) const295   set_size(std::size_t) const noexcept
296   {
297     return 0;
298   }
299 
300   BOOST_STATIC_STRING_CPP14_CONSTEXPR
301   void
term_impl() const302   term_impl() const noexcept { }
303 
304 private:
305   static constexpr const value_type null_{};
306 };
307 
308 // This is only needed in C++14 and lower.
309 // see http://eel.is/c++draft/depr.static.constexpr
310 #ifndef BOOST_STATIC_STRING_CPP17
311 template<typename CharT, typename Traits>
312 constexpr
313 const
314 typename static_string_base<0, CharT, Traits>::value_type
315 static_string_base<0, CharT, Traits>::
316 null_;
317 #endif
318 
319 template<typename CharT, typename Traits>
320 BOOST_STATIC_STRING_CPP14_CONSTEXPR
321 inline
322 int
lexicographical_compare(const CharT * s1,std::size_t n1,const CharT * s2,std::size_t n2)323 lexicographical_compare(
324   const CharT* s1,
325   std::size_t n1,
326   const CharT* s2,
327   std::size_t n2) noexcept
328 {
329   if(n1 < n2)
330     return Traits::compare(
331       s1, s2, n1) <= 0 ? -1 : 1;
332   if(n1 > n2)
333     return Traits::compare(
334       s1, s2, n2) >= 0 ? 1 : -1;
335   return Traits::compare(s1, s2, n1);
336 }
337 
338 template<typename Traits, typename Integer>
339 inline
340 char*
integer_to_string(char * str_end,Integer value,std::true_type)341 integer_to_string(
342   char* str_end,
343   Integer value,
344   std::true_type) noexcept
345 {
346   if (value == 0)
347   {
348     Traits::assign(*--str_end, '0');
349     return str_end;
350   }
351   if (value < 0)
352   {
353     const bool is_min = value == std::numeric_limits<Integer>::min();
354     // negation of a min value cannot be represented
355     if (is_min)
356       value = std::numeric_limits<Integer>::max();
357     else
358       value = -value;
359     const auto last_char = str_end - 1;
360     for (; value > 0; value /= 10)
361       Traits::assign(*--str_end, "0123456789"[value % 10]);
362     // minimum values are powers of 2, so it will
363     // never terminate with a 9.
364     if (is_min)
365       Traits::assign(*last_char, Traits::to_char_type(
366         Traits::to_int_type(*last_char) + 1));
367     Traits::assign(*--str_end, '-');
368     return str_end;
369   }
370   for (; value > 0; value /= 10)
371     Traits::assign(*--str_end, "0123456789"[value % 10]);
372   return str_end;
373 }
374 
375 template<typename Traits, typename Integer>
376 inline
377 char*
integer_to_string(char * str_end,Integer value,std::false_type)378 integer_to_string(
379   char* str_end,
380   Integer value,
381   std::false_type) noexcept
382 {
383   if (value == 0)
384   {
385     Traits::assign(*--str_end, '0');
386     return str_end;
387   }
388   for (; value > 0; value /= 10)
389     Traits::assign(*--str_end, "0123456789"[value % 10]);
390   return str_end;
391 }
392 
393 template<typename Traits, typename Integer>
394 inline
395 wchar_t*
integer_to_wstring(wchar_t * str_end,Integer value,std::true_type)396 integer_to_wstring(
397   wchar_t* str_end,
398   Integer value,
399   std::true_type) noexcept
400 {
401   if (value == 0)
402   {
403     Traits::assign(*--str_end, L'0');
404     return str_end;
405   }
406   if (value < 0)
407   {
408     const bool is_min = value == std::numeric_limits<Integer>::min();
409     // negation of a min value cannot be represented
410     if (is_min)
411       value = std::numeric_limits<Integer>::max();
412     else
413       value = -value;
414     const auto last_char = str_end - 1;
415     for (; value > 0; value /= 10)
416       Traits::assign(*--str_end, L"0123456789"[value % 10]);
417     // minimum values are powers of 2, so it will
418     // never terminate with a 9.
419     if (is_min)
420       Traits::assign(*last_char, Traits::to_char_type(
421         Traits::to_int_type(*last_char) + 1));
422     Traits::assign(*--str_end, L'-');
423     return str_end;
424   }
425   for (; value > 0; value /= 10)
426     Traits::assign(*--str_end, L"0123456789"[value % 10]);
427   return str_end;
428 }
429 
430 template<typename Traits, typename Integer>
431 inline
432 wchar_t*
integer_to_wstring(wchar_t * str_end,Integer value,std::false_type)433 integer_to_wstring(
434   wchar_t* str_end,
435   Integer value,
436   std::false_type) noexcept
437 {
438   if (value == 0)
439   {
440     Traits::assign(*--str_end, L'0');
441     return str_end;
442   }
443   for (; value > 0; value /= 10)
444     Traits::assign(*--str_end, L"0123456789"[value % 10]);
445   return str_end;
446 }
447 
448 template<std::size_t N, typename Integer>
449 inline
450 static_string<N>
to_static_string_int_impl(Integer value)451 to_static_string_int_impl(Integer value) noexcept
452 {
453   char buffer[N];
454   const auto digits_end = std::end(buffer);
455   const auto digits_begin = integer_to_string<std::char_traits<char>, Integer>(
456     digits_end, value, std::is_signed<Integer>{});
457   return static_string<N>(digits_begin, std::distance(digits_begin, digits_end));
458 }
459 
460 template<std::size_t N, typename Integer>
461 inline
462 static_wstring<N>
to_static_wstring_int_impl(Integer value)463 to_static_wstring_int_impl(Integer value) noexcept
464 {
465   wchar_t buffer[N];
466   const auto digits_end = std::end(buffer);
467   const auto digits_begin = integer_to_wstring<std::char_traits<wchar_t>, Integer>(
468     digits_end, value, std::is_signed<Integer>{});
469   return static_wstring<N>(digits_begin, std::distance(digits_begin, digits_end));
470 }
471 
472 BOOST_STATIC_STRING_CPP11_CONSTEXPR
473 inline
474 int
count_digits(std::size_t value)475 count_digits(std::size_t value)
476 {
477   return value < 10 ? 1 : count_digits(value / 10) + 1;
478 }
479 
480 // Ignore -Wformat-truncation, we know what
481 // we are doing here. The version check does
482 // not need to be extremely precise.
483 #if defined(__GNUC__) && __GNUC__ >= 7
484 #pragma GCC diagnostic push
485 #pragma GCC diagnostic ignored "-Wformat-truncation"
486 #endif
487 
488 template<std::size_t N>
489 inline
490 static_string<N>
to_static_string_float_impl(double value)491 to_static_string_float_impl(double value) noexcept
492 {
493   // we have to assume here that no reasonable implementation
494   // will require more than 2^63 chars to represent a float value.
495   const long long narrow =
496     static_cast<long long>(N);
497   // extra one needed for null terminator
498   char buffer[N + 1];
499   // we know that a formatting error will not occur, so
500   // we assume that the result is always positive
501   if (std::size_t(std::snprintf(buffer, N + 1, "%f", value)) > N)
502   {
503     // the + 4 is for the decimal, 'e',
504     // its sign, and the sign of the integral portion
505     const int reserved_count =
506       (std::max)(2, count_digits(
507       std::numeric_limits<double>::max_exponent10)) + 4;
508     const int precision = narrow > reserved_count ?
509       N - reserved_count : 0;
510     // switch to scientific notation
511     std::snprintf(buffer, N + 1, "%.*e", precision, value);
512   }
513   // this will not throw
514   return static_string<N>(buffer);
515 }
516 
517 template<std::size_t N>
518 inline
519 static_string<N>
to_static_string_float_impl(long double value)520 to_static_string_float_impl(long double value) noexcept
521 {
522   // we have to assume here that no reasonable implementation
523   // will require more than 2^63 chars to represent a float value.
524   const long long narrow =
525     static_cast<long long>(N);
526   // extra one needed for null terminator
527   char buffer[N + 1];
528   // snprintf returns the number of characters
529   // that would have been written
530   // we know that a formatting error will not occur, so
531   // we assume that the result is always positive
532   if (std::size_t(std::snprintf(buffer, N + 1, "%Lf", value)) > N)
533   {
534     // the + 4 is for the decimal, 'e',
535     // its sign, and the sign of the integral portion
536     const int reserved_count =
537       (std::max)(2, count_digits(
538       std::numeric_limits<long double>::max_exponent10)) + 4;
539     const int precision = narrow > reserved_count ?
540       N - reserved_count : 0;
541     // switch to scientific notation
542     std::snprintf(buffer, N + 1, "%.*Le", precision, value);
543   }
544   // this will not throw
545   return static_string<N>(buffer);
546 }
547 
548 template<std::size_t N>
549 inline
550 static_wstring<N>
to_static_wstring_float_impl(double value)551 to_static_wstring_float_impl(double value) noexcept
552 {
553   // we have to assume here that no reasonable implementation
554   // will require more than 2^63 chars to represent a float value.
555   const long long narrow =
556     static_cast<long long>(N);
557   // extra one needed for null terminator
558   wchar_t buffer[N + 1];
559   // swprintf returns a negative number if it can't
560   // fit all the characters in the buffer.
561   // mingw has a non-standard swprintf, so
562   // this just covers all the bases. short
563   // circuit evaluation will ensure that the
564   // second operand is not evaluated on conforming
565   // implementations.
566   const long long num_written =
567     std::swprintf(buffer, N + 1, L"%f", value);
568   if (num_written < 0 ||
569     num_written > narrow)
570   {
571     // the + 4 is for the decimal, 'e',
572     // its sign, and the sign of the integral portion
573     const int reserved_count =
574       (std::max)(2, count_digits(
575       std::numeric_limits<double>::max_exponent10)) + 4;
576     const int precision = narrow > reserved_count ?
577       N - reserved_count : 0;
578     // switch to scientific notation
579     std::swprintf(buffer, N + 1, L"%.*e", precision, value);
580   }
581   // this will not throw
582   return static_wstring<N>(buffer);
583 }
584 
585 template<std::size_t N>
586 inline
587 static_wstring<N>
to_static_wstring_float_impl(long double value)588 to_static_wstring_float_impl(long double value) noexcept
589 {
590   // we have to assume here that no reasonable implementation
591   // will require more than 2^63 chars to represent a float value.
592   const long long narrow =
593     static_cast<long long>(N);
594   // extra one needed for null terminator
595   wchar_t buffer[N + 1];
596   // swprintf returns a negative number if it can't
597   // fit all the characters in the buffer.
598   // mingw has a non-standard swprintf, so
599   // this just covers all the bases. short
600   // circuit evaluation will ensure that the
601   // second operand is not evaluated on conforming
602   // implementations.
603   const long long num_written =
604     std::swprintf(buffer, N + 1, L"%Lf", value);
605   if (num_written < 0 ||
606     num_written > narrow)
607   {
608     // the + 4 is for the decimal, 'e',
609     // its sign, and the sign of the integral portion
610     const int reserved_count =
611       (std::max)(2, count_digits(
612       std::numeric_limits<long double>::max_exponent10)) + 4;
613     const int precision = narrow > reserved_count ?
614       N - reserved_count : 0;
615     // switch to scientific notation
616     std::swprintf(buffer, N + 1, L"%.*Le", precision, value);
617   }
618   // this will not throw
619   return static_wstring<N>(buffer);
620 }
621 
622 #if defined(__GNUC__) && __GNUC__ >= 7
623 #pragma GCC diagnostic pop
624 #endif
625 
626 template<typename Traits, typename CharT, typename ForwardIterator>
627 BOOST_STATIC_STRING_CPP14_CONSTEXPR
628 inline
629 ForwardIterator
find_not_of(ForwardIterator first,ForwardIterator last,const CharT * str,std::size_t n)630 find_not_of(
631   ForwardIterator first,
632   ForwardIterator last,
633   const CharT* str,
634   std::size_t n) noexcept
635 {
636   for (; first != last; ++first)
637     if (!Traits::find(str, n, *first))
638       return first;
639   return last;
640 }
641 
642 // constexpr search for C++14
643 template<typename ForwardIt1, typename ForwardIt2, typename BinaryPredicate>
644 BOOST_STATIC_STRING_CPP14_CONSTEXPR
645 inline
646 ForwardIt1
search(ForwardIt1 first,ForwardIt1 last,ForwardIt2 s_first,ForwardIt2 s_last,BinaryPredicate p)647 search(
648   ForwardIt1 first,
649   ForwardIt1 last,
650   ForwardIt2 s_first,
651   ForwardIt2 s_last,
652   BinaryPredicate p)
653 {
654   for (; ; ++first)
655   {
656     ForwardIt1 it = first;
657     for (ForwardIt2 s_it = s_first; ; ++it, ++s_it)
658     {
659       if (s_it == s_last)
660         return first;
661       if (it == last)
662         return last;
663       if (!p(*it, *s_it))
664         break;
665     }
666   }
667 }
668 
669 template<typename InputIt, typename ForwardIt, typename BinaryPredicate>
670 BOOST_STATIC_STRING_CPP14_CONSTEXPR
671 inline
672 InputIt
find_first_of(InputIt first,InputIt last,ForwardIt s_first,ForwardIt s_last,BinaryPredicate p)673 find_first_of(
674   InputIt first,
675   InputIt last,
676   ForwardIt s_first,
677   ForwardIt s_last,
678   BinaryPredicate p)
679 {
680   for (; first != last; ++first)
681     for (ForwardIt it = s_first; it != s_last; ++it)
682       if (p(*first, *it))
683         return first;
684   return last;
685 }
686 
687 // KRYSTIAN TODO: add a constexpr rotate
688 
689 // Check if a pointer lies within the range {src_first, src_last)
690 // without unspecified behavior, allowing it to be used
691 // in a constant evaluation.
692 template<typename T>
693 BOOST_STATIC_STRING_CPP14_CONSTEXPR
694 inline
695 bool
ptr_in_range(const T * src_first,const T * src_last,const T * ptr)696 ptr_in_range(
697   const T* src_first,
698   const T* src_last,
699   const T* ptr)
700 {
701 #if defined(BOOST_STATIC_STRING_CPP14) && \
702 defined(BOOST_STATIC_STRING_IS_CONST_EVAL)
703   // Our second best option is to use is_constant_evaluated
704   // and a loop that checks for equality, since equality for
705   // pointer to object types is never unspecified in this case.
706   if (BOOST_STATIC_STRING_IS_CONST_EVAL)
707   {
708     for (; src_first != src_last; ++src_first)
709       if (ptr == src_first)
710         return true;
711     return false;
712   }
713 #endif
714   // We want to make this usable in constant expressions as much as possible
715   // while retaining the guarentee that the comparison has a strict total ordering.
716   // We also want this to be fast. Since different compilers have differing levels
717   // of conformance, we will settle for the best option that is available.
718   // We don't care about this in C++11, since this function would have
719   // no applications in constant expressions.
720 #if defined(BOOST_STATIC_STRING_CPP14) && \
721 defined(BOOST_STATIC_STRING_NO_PTR_COMP_FUNCTIONS)
722   // If library comparison functions don't work,
723   // we can use try builtin comparison operators instead.
724   return ptr >= src_first && ptr < src_last;
725 #else
726   // Use the library comparison functions if we can't use
727   // is_constant_evaluated or if we don't need to.
728   return std::greater_equal<const T*>()(ptr, src_first) &&
729     std::less<const T*>()(ptr, src_last);
730 #endif
731 }
732 
733 // This workaround is for gcc 5,
734 // which prohibits throw expressions in constexpr
735 // functions, but for some reason permits them in
736 // constructors.
737 #ifdef BOOST_STATIC_STRING_GCC5_BAD_CONSTEXPR
738 template<typename Exception>
739 struct throw_exception
740 {
741   BOOST_STATIC_STRING_NORETURN
742   BOOST_STATIC_STRING_CPP14_CONSTEXPR
throw_exceptionboost::static_strings::detail::throw_exception743   throw_exception(const char* msg)
744   {
745     BOOST_STATIC_STRING_THROW(Exception(msg));
746   }
747 };
748 #else
749 template<typename Exception>
750 BOOST_STATIC_STRING_NORETURN
751 inline
752 void
throw_exception(const char * msg)753 throw_exception(const char* msg)
754 {
755   BOOST_STATIC_STRING_THROW(Exception(msg));
756 }
757 #endif
758 
759 } // detail
760 #endif
761 
762 //--------------------------------------------------------------------------
763 //
764 // static_string
765 //
766 //--------------------------------------------------------------------------
767 
768 /** A fixed-capacity string.
769 
770     These objects behave like `std::string` except that the storage
771     is not dynamically allocated but rather fixed in size, and
772     stored in the object itself.
773 
774     These strings offer performance advantages when an algorithm
775     can execute with a reasonable upper limit on the size of a value.
776 
777     @par Aliases
778 
779     The following alias templates are provided for convenience:
780 
781     @code
782     template<std::size_t N>
783     using static_string =
784       basic_static_string<N, char, std::char_traits<char>>;
785     @endcode
786 
787     @code
788     template<std::size_t N>
789     using static_wstring =
790       basic_static_string<N, wchar_t, std::char_traits<wchar_t>>;
791     @endcode
792 
793     @code
794     template<std::size_t N>
795     using static_u16string =
796       basic_static_string<N, char16_t, std::char_traits<char16_t>>;
797     @endcode
798 
799     @code
800     template<std::size_t N>
801     using static_u32string =
802       basic_static_string<N, char32_t, std::char_traits<char32_t>>;
803     @endcode
804 
805     Addtionally, the alias template `static_u8string` is provided in C++20
806 
807     @code
808     template<std::size_t N>
809     using static_u8string =
810       basic_static_string<N, char8_t, std::char_traits<char8_t>>;
811     @endcode
812 
813     @see to_static_string
814 */
815 template<std::size_t N, typename CharT,
816   typename Traits = std::char_traits<CharT>>
817 class basic_static_string
818 #ifndef BOOST_STATIC_STRING_DOCS
819   : private detail::static_string_base<N, CharT, Traits>
820 #endif
821 {
822 private:
823   template<std::size_t, class, class>
824   friend class basic_static_string;
825 public:
826   //--------------------------------------------------------------------------
827   //
828   // Member types
829   //
830   //--------------------------------------------------------------------------
831 
832   /// The traits type.
833   using traits_type = Traits;
834 
835   /// The character type.
836   using value_type = typename traits_type::char_type;
837 
838   /// The size type.
839   using size_type = std::size_t;
840 
841   /// The difference type.
842   using difference_type = std::ptrdiff_t;
843 
844   /// The pointer type.
845   using pointer = value_type*;
846 
847   /// The reference type.
848   using reference = value_type&;
849 
850   /// The constant pointer type.
851   using const_pointer = const value_type*;
852 
853   /// The constant reference type.
854   using const_reference = const value_type&;
855 
856   /// The iterator type.
857   using iterator = value_type*;
858 
859   /// The constant iterator type.
860   using const_iterator = const value_type*;
861 
862   /// The reverse iterator type.
863   using reverse_iterator =
864     std::reverse_iterator<iterator>;
865 
866   /// The constant reverse iterator type.
867   using const_reverse_iterator =
868     std::reverse_iterator<const_iterator>;
869 
870   /// The string view type.
871   using string_view_type =
872     basic_string_view<value_type, traits_type>;
873 
874   //--------------------------------------------------------------------------
875   //
876   // Constants
877   //
878   //--------------------------------------------------------------------------
879 
880   /// Maximum size of the string excluding any null terminator
881   static constexpr size_type static_capacity = N;
882 
883   /// A special index
884   static constexpr size_type npos = size_type(-1);
885 
886   //--------------------------------------------------------------------------
887   //
888   // Construction
889   //
890   //--------------------------------------------------------------------------
891 
892   /** Constructor.
893 
894       Construct an empty string
895   */
896   BOOST_STATIC_STRING_CPP11_CONSTEXPR
basic_static_string()897   basic_static_string() noexcept
898   {
899 #ifdef BOOST_STATIC_STRING_CPP20
900     term();
901 #endif
902   }
903 
904   /** Constructor.
905 
906       Construct the string with `count` copies of character `ch`.
907 
908       The behavior is undefined if `count >= npos`
909   */
910   BOOST_STATIC_STRING_CPP14_CONSTEXPR
basic_static_string(size_type count,value_type ch)911   basic_static_string(
912     size_type count,
913     value_type ch)
914   {
915     assign(count, ch);
916   }
917 
918   /** Constructor.
919 
920       Construct with a substring (pos, other.size()) of `other`.
921   */
922   template<std::size_t M>
923   BOOST_STATIC_STRING_CPP14_CONSTEXPR
basic_static_string(const basic_static_string<M,CharT,Traits> & other,size_type pos)924   basic_static_string(
925     const basic_static_string<M, CharT, Traits>& other,
926     size_type pos)
927   {
928     assign(other, pos);
929   }
930 
931   /** Constructor.
932 
933       Construct with a substring (pos, count) of `other`.
934   */
935   template<std::size_t M>
936   BOOST_STATIC_STRING_CPP14_CONSTEXPR
basic_static_string(const basic_static_string<M,CharT,Traits> & other,size_type pos,size_type count)937   basic_static_string(
938     const basic_static_string<M, CharT, Traits>& other,
939     size_type pos,
940     size_type count)
941   {
942     assign(other, pos, count);
943   }
944 
945   /** Constructor.
946 
947       Construct with the first `count` characters of `s`, including nulls.
948     */
949   BOOST_STATIC_STRING_CPP14_CONSTEXPR
basic_static_string(const_pointer s,size_type count)950   basic_static_string(
951     const_pointer s,
952     size_type count)
953   {
954     assign(s, count);
955   }
956 
957   /** Constructor.
958 
959       Construct from a null terminated string.
960   */
961   BOOST_STATIC_STRING_CPP14_CONSTEXPR
basic_static_string(const_pointer s)962   basic_static_string(const_pointer s)
963   {
964     assign(s);
965   }
966 
967   /** Constructor.
968 
969       Construct from a range of characters
970   */
971   template<typename InputIterator
972 #ifndef BOOST_STATIC_STRING_DOCS
973     , typename std::enable_if<
974       detail::is_input_iterator<InputIterator>
975         ::value>::type* = nullptr
976 #endif
977   >
978   BOOST_STATIC_STRING_CPP14_CONSTEXPR
basic_static_string(InputIterator first,InputIterator last)979   basic_static_string(
980     InputIterator first,
981     InputIterator last)
982   {
983     // KRYSTIAN TODO: we can use a better algorithm if this is a forward iterator
984     assign(first, last);
985   }
986 
987   /** Constructor.
988 
989       Copy constructor.
990   */
991   BOOST_STATIC_STRING_CPP14_CONSTEXPR
basic_static_string(const basic_static_string & other)992   basic_static_string(const basic_static_string& other) noexcept
993   {
994     assign(other);
995   }
996 
997   /** Constructor.
998 
999       Copy constructor.
1000   */
1001   template<std::size_t M>
1002   BOOST_STATIC_STRING_CPP14_CONSTEXPR
basic_static_string(const basic_static_string<M,CharT,Traits> & other)1003   basic_static_string(
1004     const basic_static_string<M, CharT, Traits>& other)
1005   {
1006     assign(other);
1007   }
1008 
1009   /** Constructor.
1010 
1011       Construct from an initializer list
1012   */
1013   BOOST_STATIC_STRING_CPP14_CONSTEXPR
basic_static_string(std::initializer_list<value_type> init)1014   basic_static_string(std::initializer_list<value_type> init)
1015   {
1016     assign(init.begin(), init.size());
1017   }
1018 
1019   /** Constructor.
1020 
1021       Construct from a object convertible to `string_view_type`
1022   */
1023   template<typename T
1024 #ifndef BOOST_STATIC_STRING_DOCS
1025     , typename = detail::enable_if_viewable_t<T, CharT, Traits>
1026 #endif
1027   >
1028   explicit
1029   BOOST_STATIC_STRING_CPP14_CONSTEXPR
basic_static_string(const T & t)1030   basic_static_string(const T& t)
1031   {
1032     assign(t);
1033   }
1034 
1035   /** Constructor.
1036 
1037       Construct from any object convertible to `string_view_type`.
1038 
1039       The range (pos, n) is extracted from the value
1040       obtained by converting `t` to `string_view_type`,
1041       and used to construct the string.
1042   */
1043   template<typename T
1044 #ifndef BOOST_STATIC_STRING_DOCS
1045     , typename = detail::enable_if_viewable_t<T, CharT, Traits>
1046 #endif
1047   >
1048   BOOST_STATIC_STRING_CPP14_CONSTEXPR
basic_static_string(const T & t,size_type pos,size_type n)1049   basic_static_string(
1050     const T& t,
1051     size_type pos,
1052     size_type n)
1053   {
1054     assign(t, pos, n);
1055   }
1056 
1057   //--------------------------------------------------------------------------
1058   //
1059   // Assignment
1060   //
1061   //--------------------------------------------------------------------------
1062 
1063   /** Assign to the string.
1064 
1065       Replaces the contents with those of
1066       the string `s`.
1067 
1068       @par Complexity
1069 
1070       Linear in `s.size()`.
1071 
1072       @par Exception Safety
1073 
1074       Strong guarantee.
1075 
1076       @tparam M The size of the other string.
1077 
1078       @return `*this`
1079 
1080       @param s The string to replace
1081       the contents with.
1082 
1083       @throw std::length_error `s.size() > max_size()`.
1084   */
1085   template<std::size_t M>
1086   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1087   basic_static_string&
operator =(const basic_static_string<M,CharT,Traits> & s)1088   operator=(const basic_static_string<M, CharT, Traits>& s)
1089   {
1090     return assign(s);
1091   }
1092 
1093   /** Assign to the string.
1094 
1095       Replaces the contents with those of
1096       `{s, s + traits_type::length(s))`.
1097 
1098       @par Complexity
1099 
1100       Linear in `count`.
1101 
1102       @par Exception Safety
1103 
1104       Strong guarantee.
1105 
1106       @return `*this`
1107 
1108       @param s A pointer to the string to copy from.
1109 
1110       @throw std::length_error `traits_type::length(s) > max_size()`.
1111   */
1112   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1113   basic_static_string&
operator =(const_pointer s)1114   operator=(const_pointer s)
1115   {
1116     return assign(s);
1117   }
1118 
1119   /** Assign to the string.
1120 
1121       Replaces the contents with a single copy of
1122       the character `ch`.
1123 
1124       @par Complexity
1125 
1126       Constant.
1127 
1128       @par Exception Safety
1129 
1130       Strong guarantee.
1131 
1132       @return `*this`
1133 
1134       @param ch The character to assign to.
1135 
1136       @throw std::length_error `count > max_size()`.
1137   */
1138   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1139   basic_static_string&
operator =(value_type ch)1140   operator=(value_type ch)
1141   {
1142     return assign_char(ch,
1143       std::integral_constant<bool, (N > 0)>{});
1144   }
1145 
1146   /** Assign to the string.
1147 
1148       Replaces the contents with those of the
1149       initializer list `ilist`.
1150 
1151       @par Complexity
1152 
1153       Linear in `init.size()`.
1154 
1155       @par Exception Safety
1156 
1157       Strong guarantee.
1158 
1159       @return `*this`
1160 
1161       @param ilist The initializer list to copy from.
1162 
1163       @throw std::length_error `ilist.size() > max_size()`.
1164   */
1165   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1166   basic_static_string&
operator =(std::initializer_list<value_type> ilist)1167   operator=(std::initializer_list<value_type> ilist)
1168   {
1169     return assign(ilist);
1170   }
1171 
1172   /** Assign to the string.
1173 
1174       Replaces the contents with those of
1175       `sv`, where `sv` is `string_view_type(t)`.
1176 
1177       @par Complexity
1178 
1179       Linear in `sv.size()`.
1180 
1181       @par Exception Safety
1182 
1183       Strong guarantee.
1184 
1185       @note
1186 
1187       The view can contain null characters.
1188 
1189       @tparam T A type convertible to `string_view_type`.
1190 
1191       @par Constraints
1192 
1193       @code
1194       std::is_convertible<const T&, string_view>::value &&
1195       !std::is_convertible<const T&, const CharT*>::value
1196       @endcode
1197 
1198       @return `*this`
1199 
1200       @param t The object to assign from.
1201 
1202       @throw std::length_error `sv.size() > max_size()`.
1203   */
1204   template<typename T
1205 #ifndef BOOST_STATIC_STRING_DOCS
1206     , typename = detail::enable_if_viewable_t<T, CharT, Traits>
1207 #endif
1208   >
1209   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1210   basic_static_string&
operator =(const T & t)1211   operator=(const T& t)
1212   {
1213     return assign(t);
1214   }
1215 
1216   /** Assign to the string.
1217 
1218       Replaces the contents with `count` copies of
1219       character `ch`.
1220 
1221       @par Complexity
1222 
1223       Linear in `count`.
1224 
1225       @par Exception Safety
1226 
1227       Strong guarantee.
1228 
1229       @return `*this`
1230 
1231       @param count The size of the resulting string.
1232 
1233       @param ch The value to initialize characters
1234       of the string with.
1235 
1236       @throw std::length_error `count > max_size()`.
1237   */
1238   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1239   basic_static_string&
1240   assign(
1241     size_type count,
1242     value_type ch);
1243 
1244   /** Assign to the string.
1245 
1246       Replaces the contents with those of
1247       the string `s`.
1248 
1249       @par Complexity
1250 
1251       Linear in `s.size()`.
1252 
1253       @par Exception Safety
1254 
1255       Strong guarantee.
1256 
1257       @tparam M The size of the other string.
1258 
1259       @return `*this`
1260 
1261       @param s The string to replace
1262       the contents with.
1263 
1264       @throw std::length_error `s.size() > max_size()`.
1265   */
1266   template<std::size_t M
1267 #ifndef BOOST_STATIC_STRING_DOCS
1268   , typename std::enable_if<(M < N)>::type* = nullptr
1269 #endif
1270   >
1271   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1272   basic_static_string&
assign(const basic_static_string<M,CharT,Traits> & s)1273   assign(const basic_static_string<M, CharT, Traits>& s)
1274   {
1275     return assign_unchecked(s.data(), s.size());
1276   }
1277 
1278 #ifndef BOOST_STATIC_STRING_DOCS
1279   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1280   basic_static_string&
assign(const basic_static_string & s)1281   assign(const basic_static_string& s) noexcept
1282   {
1283     if (this == &s)
1284       return *this;
1285     return assign_unchecked(s.data(), s.size());
1286   }
1287 
1288   template<std::size_t M,
1289     typename std::enable_if<(M > N)>::type* = nullptr>
1290   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1291   basic_static_string&
assign(const basic_static_string<M,CharT,Traits> & s)1292   assign(const basic_static_string<M, CharT, Traits>& s)
1293   {
1294     return assign(s.data(), s.size());
1295   }
1296 #endif
1297 
1298   /** Assign to the string.
1299 
1300       Replaces the contents with those of the string `sub`,
1301       where `sub` is `s.substr(pos, count)`.
1302 
1303       @par Complexity
1304 
1305       Linear in `sub.size()`.
1306 
1307       @par Exception Safety
1308 
1309       Strong guarantee.
1310 
1311       @tparam M The capacity of the other string.
1312 
1313       @return `*this`
1314 
1315       @param s The string to replace
1316       the contents with.
1317 
1318       @param pos The index at which to begin the substring.
1319 
1320       @param count The size of the substring. The default
1321       argument for this parameter is @ref npos.
1322 
1323       @throw std::length_error `sub.size() > max_size()`.
1324   */
1325   template<std::size_t M>
1326   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1327   basic_static_string&
assign(const basic_static_string<M,CharT,Traits> & s,size_type pos,size_type count=npos)1328   assign(
1329     const basic_static_string<M, CharT, Traits>& s,
1330     size_type pos,
1331     size_type count = npos)
1332   {
1333     return assign(s.data() + pos, s.capped_length(pos, count));
1334   }
1335 
1336   /** Assign to the string.
1337 
1338       Replaces the contents with those of `{s, s + count)`.
1339 
1340       @par Complexity
1341 
1342       Linear in `count`.
1343 
1344       @par Exception Safety
1345 
1346       Strong guarantee.
1347 
1348       @note
1349 
1350       The range can contain null characters.
1351 
1352       @return `*this`
1353 
1354       @param count The number of characters to copy.
1355 
1356       @param s A pointer to the string to copy from.
1357 
1358       @throw std::length_error `count > max_size()`.
1359     */
1360   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1361   basic_static_string&
1362   assign(
1363     const_pointer s,
1364     size_type count);
1365 
1366   /** Assign to the string.
1367 
1368       Replaces the contents with those of
1369       `{s, s + traits_type::length(s))`.
1370 
1371       @par Complexity
1372 
1373       Linear in `count`.
1374 
1375       @par Exception Safety
1376 
1377       Strong guarantee.
1378 
1379       @return `*this`
1380 
1381       @param s A pointer to the string to copy from.
1382 
1383       @throw std::length_error `traits_type::length(s) > max_size()`.
1384   */
1385   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1386   basic_static_string&
assign(const_pointer s)1387   assign(const_pointer s)
1388   {
1389     return assign(s, traits_type::length(s));
1390   }
1391 
1392   /** Assign to the string.
1393 
1394       Replaces the contents with the characters
1395       in the range `{first, last)`.
1396 
1397       @par Complexity
1398 
1399       Linear in `std::distance(first, last)`.
1400 
1401       @par Exception Safety
1402 
1403       Strong guarantee.
1404 
1405       @tparam InputIterator The type of the iterators.
1406 
1407       @par Constraints
1408 
1409       `InputIterator` satisfies __InputIterator__.
1410 
1411       @return `*this`
1412 
1413       @param first An iterator referring to the
1414       first character to assign.
1415 
1416       @param last An iterator past the end
1417       of the range to assign from.
1418 
1419       @throw std::length_error `std::distance(first, last) > max_size()`.
1420   */
1421   template<typename InputIterator>
1422   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1423 #ifdef BOOST_STATIC_STRING_DOCS
1424   basic_static_string&
1425 #else
1426   typename std::enable_if<
1427     detail::is_input_iterator<InputIterator>::value,
1428       basic_static_string&>::type
1429 #endif
1430   assign(
1431     InputIterator first,
1432     InputIterator last);
1433 
1434   /** Assign to the string.
1435 
1436       Replaces the contents with those of the
1437       initializer list `ilist`.
1438 
1439       @par Complexity
1440 
1441       Linear in `init.size()`.
1442 
1443       @par Exception Safety
1444 
1445       Strong guarantee.
1446 
1447       @return `*this`
1448 
1449       @param ilist The initializer list to copy from.
1450 
1451       @throw std::length_error `ilist.size() > max_size()`.
1452   */
1453   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1454   basic_static_string&
assign(std::initializer_list<value_type> ilist)1455   assign(
1456     std::initializer_list<value_type> ilist)
1457   {
1458     return assign(ilist.begin(), ilist.end());
1459   }
1460 
1461   /** Assign to the string.
1462 
1463       Replaces the contents with those of
1464       `sv`, where `sv` is `string_view_type(t)`.
1465 
1466       @par Complexity
1467 
1468       Linear in `sv.size()`.
1469 
1470       @par Exception Safety
1471 
1472       Strong guarantee.
1473 
1474       @note
1475 
1476       The view can contain null characters.
1477 
1478       @tparam T A type convertible to `string_view_type`.
1479 
1480       @par Constraints
1481 
1482       @code
1483       std::is_convertible<const T&, string_view>::value &&
1484       !std::is_convertible<const T&, const CharT*>::value
1485       @endcode
1486 
1487       @return `*this`
1488 
1489       @param t The object to assign from.
1490 
1491       @throw std::length_error `sv.size() > max_size()`.
1492   */
1493   template<typename T
1494 #ifndef BOOST_STATIC_STRING_DOCS
1495     , typename = detail::enable_if_viewable_t<T, CharT, Traits>
1496 #endif
1497   >
1498   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1499   basic_static_string&
assign(const T & t)1500   assign(const T& t)
1501   {
1502     const string_view_type sv = t;
1503     return assign(sv.data(), sv.size());
1504   }
1505 
1506   /** Assign to the string.
1507 
1508       Replaces the contents with those of the substring `sv`,
1509       where `sv` is `string_view_type(t).substr(pos, count)`.
1510 
1511       @par Complexity
1512 
1513       Linear in `sv.size()`.
1514 
1515       @par Exception Safety
1516 
1517       Strong guarantee.
1518 
1519       @note
1520 
1521       The view can contain null characters.
1522 
1523       @tparam T A type convertible to `string_view_type`.
1524 
1525       @par Constraints
1526 
1527       @code
1528       std::is_convertible<const T&, string_view>::value &&
1529       !std::is_convertible<const T&, const CharT*>::value
1530       @endcode
1531 
1532       @return `*this`
1533 
1534       @param t The object to assign from.
1535 
1536       @param pos The index at which to begin the substring.
1537 
1538       @param count The size of the substring. The default
1539       argument for this parameter is @ref npos.
1540 
1541       @throw std::length_error `sv.size() > max_size()`.
1542   */
1543   template<typename T
1544 #ifndef BOOST_STATIC_STRING_DOCS
1545     , typename = detail::enable_if_viewable_t<T, CharT, Traits>
1546 #endif
1547   >
1548   basic_static_string&
assign(const T & t,size_type pos,size_type count=npos)1549   assign(
1550     const T& t,
1551     size_type pos,
1552     size_type count = npos)
1553   {
1554     const auto sv = string_view_type(t).substr(pos, count);
1555     return assign(sv.data(), sv.size());
1556   }
1557 
1558   //--------------------------------------------------------------------------
1559   //
1560   // Element access
1561   //
1562   //--------------------------------------------------------------------------
1563 
1564   /** Access a character with bounds checking.
1565 
1566       Returns a reference to the character at
1567       index `pos`.
1568 
1569       @par Complexity
1570 
1571       Constant.
1572 
1573       @par Exception Safety
1574 
1575       Strong guarantee.
1576 
1577       @param pos The index to access.
1578 
1579       @throw std::out_of_range `pos >= size()`
1580   */
1581   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1582   reference
at(size_type pos)1583   at(size_type pos)
1584   {
1585     if (pos >= size())
1586       detail::throw_exception<std::out_of_range>(
1587         "pos >= size()");
1588     return data()[pos];
1589   }
1590 
1591   /** Access a character with bounds checking.
1592 
1593       Returns a reference to the character at
1594       index `pos`.
1595 
1596       @par Complexity
1597 
1598       Constant.
1599 
1600       @par Exception Safety
1601 
1602       Strong guarantee.
1603 
1604       @param pos The index to access.
1605 
1606       @throw std::out_of_range `pos >= size()`
1607   */
1608   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1609   const_reference
at(size_type pos) const1610   at(size_type pos) const
1611   {
1612     if (pos >= size())
1613       detail::throw_exception<std::out_of_range>(
1614         "pos >= size()");
1615     return data()[pos];
1616   }
1617 
1618   /** Access a character.
1619 
1620       Returns a reference to the character at
1621       index `pos`.
1622 
1623       @par Complexity
1624 
1625       Constant.
1626 
1627       @par Precondition
1628 
1629       `pos >= size`
1630 
1631       @param pos The index to access.
1632   */
1633   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1634   reference
operator [](size_type pos)1635   operator[](size_type pos) noexcept
1636   {
1637     return data()[pos];
1638   }
1639 
1640   /** Access a character.
1641 
1642       Returns a reference to the character at
1643       index `pos`.
1644 
1645       @par Complexity
1646 
1647       Constant.
1648 
1649       @par Precondition
1650 
1651       `pos >= size`
1652 
1653       @param pos The index to access.
1654   */
1655   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1656   const_reference
operator [](size_type pos) const1657   operator[](size_type pos) const noexcept
1658   {
1659     return data()[pos];
1660   }
1661 
1662   /** Return the first character.
1663 
1664       Returns a reference to the first character.
1665 
1666       @par Complexity
1667 
1668       Constant.
1669 
1670       @par Precondition
1671 
1672       `not empty()`
1673   */
1674   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1675   reference
front()1676   front() noexcept
1677   {
1678     return data()[0];
1679   }
1680 
1681   /** Return the first character.
1682 
1683       Returns a reference to the first character.
1684 
1685       @par Complexity
1686 
1687       Constant.
1688 
1689       @par Precondition
1690 
1691       `not empty()`
1692   */
1693   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1694   const_reference
front() const1695   front() const noexcept
1696   {
1697     return data()[0];
1698   }
1699 
1700   /** Return the last character.
1701 
1702       Returns a reference to the last character.
1703 
1704       @par Complexity
1705 
1706       Constant.
1707 
1708       @par Precondition
1709 
1710       `not empty()`
1711   */
1712   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1713   reference
back()1714   back() noexcept
1715   {
1716     return data()[size() - 1];
1717   }
1718 
1719   /** Return the last character.
1720 
1721       Returns a reference to the last character.
1722 
1723       @par Complexity
1724 
1725       Constant.
1726 
1727       @par Precondition
1728 
1729       `not empty()`
1730   */
1731   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1732   const_reference
back() const1733   back() const noexcept
1734   {
1735     return data()[size() - 1];
1736   }
1737 
1738   /** Return a pointer to the string.
1739 
1740       Returns a pointer to the underlying array
1741       serving as storage. The value returned is such that
1742       the range `{data(), data() + size())` is always a
1743       valid range, even if the container is empty.
1744 
1745       @par Complexity
1746 
1747       Constant.
1748 
1749       @note The value returned from this function
1750       is never never a null pointer value.
1751   */
1752   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1753   pointer
data()1754   data() noexcept
1755   {
1756     return this->data_impl();
1757   }
1758 
1759   /** Return a pointer to the string.
1760 
1761       Returns a pointer to the underlying array
1762       serving as storage. The value returned is such that
1763       the range `{data(), data() + size())` is always a
1764       valid range, even if the container is empty.
1765 
1766       @par Complexity
1767 
1768       Constant.
1769 
1770       @note The value returned from this function
1771       is never never a null pointer value.
1772   */
1773   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1774   const_pointer
data() const1775   data() const noexcept
1776   {
1777     return this->data_impl();
1778   }
1779 
1780   /** Return a pointer to the string.
1781 
1782       Returns a pointer to the underlying array
1783       serving as storage. The value returned is such that
1784       the range `{c_str(), c_str() + size())` is always a
1785       valid range, even if the container is empty.
1786 
1787       @par Complexity
1788 
1789       Constant.
1790 
1791       @note The value returned from this function
1792       is never never a null pointer value.
1793   */
1794   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1795   const_pointer
c_str() const1796   c_str() const noexcept
1797   {
1798     return data();
1799   }
1800 
1801   /** Convert to a string view referring to the string.
1802 
1803       Returns a string view referring to the
1804       underlying character string.
1805 
1806       @par Complexity
1807 
1808       Constant.
1809   */
1810   BOOST_STATIC_STRING_CPP11_CONSTEXPR
operator string_view_type() const1811   operator string_view_type() const noexcept
1812   {
1813     return string_view_type(data(), size());
1814   }
1815 
1816   //--------------------------------------------------------------------------
1817   //
1818   // Iterators
1819   //
1820   //--------------------------------------------------------------------------
1821 
1822   /// Return an iterator to the beginning.
1823   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1824   iterator
begin()1825   begin() noexcept
1826   {
1827     return data();
1828   }
1829 
1830   /// Return an iterator to the beginning.
1831   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1832   const_iterator
begin() const1833   begin() const noexcept
1834   {
1835     return data();
1836   }
1837 
1838   /// Return an iterator to the beginning.
1839   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1840   const_iterator
cbegin() const1841   cbegin() const noexcept
1842   {
1843     return data();
1844   }
1845 
1846   /// Return an iterator to the end.
1847   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1848   iterator
end()1849   end() noexcept
1850   {
1851     return data() + size();
1852   }
1853 
1854   /// Return an iterator to the end.
1855   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1856   const_iterator
end() const1857   end() const noexcept
1858   {
1859     return data() + size();
1860   }
1861 
1862   /// Return an iterator to the end.
1863   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1864   const_iterator
cend() const1865   cend() const noexcept
1866   {
1867     return data() + size();
1868   }
1869 
1870   /// Return a reverse iterator to the beginning.
1871   BOOST_STATIC_STRING_CPP17_CONSTEXPR
1872   reverse_iterator
rbegin()1873   rbegin() noexcept
1874   {
1875     return reverse_iterator{end()};
1876   }
1877 
1878   /// Return a reverse iterator to the beginning.
1879   BOOST_STATIC_STRING_CPP17_CONSTEXPR
1880   const_reverse_iterator
rbegin() const1881   rbegin() const noexcept
1882   {
1883     return const_reverse_iterator{cend()};
1884   }
1885 
1886   /// Return a reverse iterator to the beginning.
1887   BOOST_STATIC_STRING_CPP17_CONSTEXPR
1888   const_reverse_iterator
crbegin() const1889   crbegin() const noexcept
1890   {
1891     return const_reverse_iterator{cend()};
1892   }
1893 
1894   /// Return a reverse iterator to the end.
1895   BOOST_STATIC_STRING_CPP17_CONSTEXPR
1896   reverse_iterator
rend()1897   rend() noexcept
1898   {
1899     return reverse_iterator{begin()};
1900   }
1901 
1902   /// Return a reverse iterator to the end.
1903   BOOST_STATIC_STRING_CPP17_CONSTEXPR
1904   const_reverse_iterator
rend() const1905   rend() const noexcept
1906   {
1907     return const_reverse_iterator{cbegin()};
1908   }
1909 
1910   /// Return a reverse iterator to the end.
1911   BOOST_STATIC_STRING_CPP17_CONSTEXPR
1912   const_reverse_iterator
crend() const1913   crend() const noexcept
1914   {
1915     return const_reverse_iterator{cbegin()};
1916   }
1917 
1918   //--------------------------------------------------------------------------
1919   //
1920   // Capacity
1921   //
1922   //--------------------------------------------------------------------------
1923 
1924   /** Return if the string is empty.
1925 
1926       Returns whether the string contains no characters.
1927 
1928       @par Complexity
1929 
1930       Constant.
1931 
1932       @return `size() == 0`
1933   */
1934   BOOST_STATIC_STRING_NODISCARD
1935   BOOST_STATIC_STRING_CPP11_CONSTEXPR
1936   bool
empty() const1937   empty() const noexcept
1938   {
1939     return size() == 0;
1940   }
1941 
1942   /** Return the size of the string.
1943 
1944       Returns the number of characters stored in the
1945       string, excluding the null terminator.
1946 
1947       @par Complexity
1948 
1949       Constant.
1950   */
1951   BOOST_STATIC_STRING_CPP11_CONSTEXPR
1952   size_type
size() const1953   size() const noexcept
1954   {
1955     return this->size_impl();
1956   }
1957 
1958   /** Return the size of the string.
1959 
1960       Returns the number of characters stored in the
1961       string, excluding the null terminator.
1962 
1963       @par Complexity
1964 
1965       Constant.
1966   */
1967   BOOST_STATIC_STRING_CPP11_CONSTEXPR
1968   size_type
length() const1969   length() const noexcept
1970   {
1971     return size();
1972   }
1973 
1974   /** Return the number of characters that can be stored.
1975 
1976       Returns the maximum size of the string, excluding the
1977       null terminator. The returned value is always `N`.
1978 
1979       @par Complexity
1980 
1981       Constant.
1982    */
1983   BOOST_STATIC_STRING_CPP11_CONSTEXPR
1984   size_type
max_size() const1985   max_size() const noexcept
1986   {
1987     return N;
1988   }
1989 
1990   /** Increase the capacity.
1991 
1992       This function has no effect.
1993 
1994       @throw std::length_error `n > max_size()`
1995   */
1996   BOOST_STATIC_STRING_CPP14_CONSTEXPR
1997   void
reserve(size_type n)1998   reserve(size_type n)
1999   {
2000     if (n > max_size())
2001       detail::throw_exception<std::length_error>(
2002         "n > max_size()");
2003   }
2004 
2005   /** Return the number of characters that can be stored.
2006 
2007       Returns the maximum size of the string, excluding the
2008       null terminator. The returned value is always `N`.
2009 
2010       @par Complexity
2011 
2012       Constant.
2013    */
2014   BOOST_STATIC_STRING_CPP11_CONSTEXPR
2015   size_type
capacity() const2016   capacity() const noexcept
2017   {
2018     return max_size();
2019   }
2020 
2021   /** Request the removal of unused capacity.
2022 
2023       This function has no effect.
2024   */
2025   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2026   void
shrink_to_fit()2027   shrink_to_fit() noexcept { }
2028 
2029   //--------------------------------------------------------------------------
2030   //
2031   // Operations
2032   //
2033   //--------------------------------------------------------------------------
2034 
2035   /** Clear the contents.
2036 
2037       Erases all characters from the string. After this
2038       call, @ref size() returns zero.
2039 
2040       @par Complexity
2041 
2042       Linear in @ref size().
2043 
2044       @note All references, pointers, or iterators
2045       referring to contained elements are invalidated. Any
2046       past-the-end iterators are also invalidated.
2047   */
2048   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2049   void
clear()2050   clear() noexcept
2051   {
2052     this->set_size(0);
2053     term();
2054   }
2055 
2056   /** Insert into the string.
2057 
2058       Inserts `count` copies of `ch` at the position `index`.
2059 
2060       @par Exception Safety
2061 
2062       Strong guarantee.
2063 
2064       @note All references, pointers, or iterators
2065       referring to contained elements are invalidated. Any
2066       past-the-end iterators are also invalidated.
2067 
2068       @return `*this`
2069 
2070       @param index The index to insert at.
2071       @param count The number of characters to insert.
2072       @param ch The character to insert.
2073 
2074       @throw std::length_error `size() + count > max_size()`
2075       @throw std::out_of_range `index > size()`
2076   */
2077   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2078   basic_static_string&
insert(size_type index,size_type count,value_type ch)2079   insert(
2080     size_type index,
2081     size_type count,
2082     value_type ch)
2083   {
2084     if (index > size())
2085       detail::throw_exception<std::out_of_range>(
2086         "index > size()");
2087     insert(begin() + index, count, ch);
2088     return *this;
2089   }
2090 
2091   /** Insert into the string.
2092 
2093       Inserts the null-terminated character string pointed to by `s`
2094       of length `count` at the position `index` where `count`
2095       is `traits_type::length(s)`.
2096 
2097       @par Exception Safety
2098 
2099       Strong guarantee.
2100 
2101       @note All references, pointers, or iterators
2102       referring to contained elements are invalidated. Any
2103       past-the-end iterators are also invalidated.
2104 
2105       @return `*this`
2106 
2107       @param index The index to insert at.
2108       @param s The string to insert.
2109 
2110       @throw std::length_error `size() + count > max_size()`
2111       @throw std::out_of_range `index > size()`
2112   */
2113   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2114   basic_static_string&
insert(size_type index,const_pointer s)2115   insert(
2116     size_type index,
2117     const_pointer s)
2118   {
2119     return insert(index, s, traits_type::length(s));
2120   }
2121 
2122   /** Insert into the string.
2123 
2124       Inserts `count` characters of the string pointed to by `s`
2125       at the position `index`.
2126 
2127       @par Exception Safety
2128 
2129       Strong guarantee.
2130 
2131       @note All references, pointers, or iterators
2132       referring to contained elements are invalidated. Any
2133       past-the-end iterators are also invalidated.
2134 
2135       @return `*this`
2136 
2137       @param index The index to insert at.
2138       @param s The string to insert.
2139       @param count The length of the string to insert.
2140 
2141       @throw std::length_error `size() + count > max_size()`
2142       @throw std::out_of_range `index > size()`
2143   */
2144   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2145   basic_static_string&
insert(size_type index,const_pointer s,size_type count)2146   insert(
2147     size_type index,
2148     const_pointer s,
2149     size_type count)
2150   {
2151     if (index > size())
2152       detail::throw_exception<std::out_of_range>(
2153         "index > size()");
2154     insert(data() + index, s, s + count);
2155     return *this;
2156   }
2157 
2158   /** Insert into the string.
2159 
2160       Inserts the string `str`
2161       at the position `index`.
2162 
2163       @par Exception Safety
2164 
2165       Strong guarantee.
2166 
2167       @note The insertion is done unchecked when
2168       the capacity of `str` differs from that of the
2169       string the function is called on.
2170 
2171       @note All references, pointers, or iterators
2172       referring to contained elements are invalidated. Any
2173       past-the-end iterators are also invalidated.
2174 
2175       @tparam M The size of the input string.
2176 
2177       @return `*this`
2178 
2179       @param index The index to insert at.
2180       @param str The string to insert.
2181 
2182       @throw std::length_error `size() + str.size() > max_size()`
2183       @throw std::out_of_range `index > size()`
2184   */
2185   template<std::size_t M>
2186   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2187   basic_static_string&
insert(size_type index,const basic_static_string<M,CharT,Traits> & str)2188   insert(
2189     size_type index,
2190     const basic_static_string<M, CharT, Traits>& str)
2191   {
2192     return insert_unchecked(index, str.data(), str.size());
2193   }
2194 
2195 #ifndef BOOST_STATIC_STRING_DOCS
2196   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2197   basic_static_string&
insert(size_type index,const basic_static_string & str)2198   insert(
2199     size_type index,
2200     const basic_static_string& str)
2201   {
2202     return insert(index, str.data(), str.size());
2203   }
2204 #endif
2205 
2206   /** Insert into the string.
2207 
2208       Inserts a string, obtained by `str.substr(index_str, count)`
2209       at the position `index`.
2210 
2211       @par Exception Safety
2212 
2213       Strong guarantee.
2214 
2215       @note The insertion is done unchecked when
2216       the capacity of `str` differs from that of the
2217       string the function is called on.
2218 
2219       @note All references, pointers, or iterators
2220       referring to contained elements are invalidated. Any
2221       past-the-end iterators are also invalidated.
2222 
2223       @tparam M The size of the input string.
2224 
2225       @return `*this`
2226 
2227       @param index The index to insert at.
2228       @param str The string from which to insert.
2229       @param index_str The index in `str` to start inserting from.
2230       @param count The number of characters to insert.
2231       The default argument for this parameter is @ref npos.
2232 
2233       @throw std::length_error `size() + str.substr(index_str, count).size() > max_size()`
2234       @throw std::out_of_range `index > size()`
2235       @throw std::out_of_range `index_str > str.size()`
2236   */
2237   template<std::size_t M>
2238   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2239   basic_static_string&
insert(size_type index,const basic_static_string<M,CharT,Traits> & str,size_type index_str,size_type count=npos)2240   insert(
2241     size_type index,
2242     const basic_static_string<M, CharT, Traits>& str,
2243     size_type index_str,
2244     size_type count = npos)
2245   {
2246     return insert_unchecked(index, str.data() + index_str, str.capped_length(index_str, count));
2247   }
2248 
2249 #ifndef BOOST_STATIC_STRING_DOCS
2250   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2251   basic_static_string&
insert(size_type index,const basic_static_string & str,size_type index_str,size_type count=npos)2252   insert(
2253     size_type index,
2254     const basic_static_string& str,
2255     size_type index_str,
2256     size_type count = npos)
2257   {
2258     return insert(index, str.data() + index_str, str.capped_length(index_str, count));
2259   }
2260 #endif
2261 
2262   /** Insert into the string.
2263 
2264       Inserts the character `ch` before the character pointed by `pos`.
2265 
2266       @par Precondition
2267 
2268       `pos` shall be vaild within `{data(), data() + size()}`
2269 
2270       @par Exception Safety
2271 
2272       Strong guarantee.
2273 
2274       @note All references, pointers, or iterators
2275       referring to contained elements are invalidated. Any
2276       past-the-end iterators are also invalidated.
2277 
2278       @return An iterator which refers to the first inserted character
2279       or `pos` if no characters were inserted
2280 
2281       @param pos The index to insert at.
2282       @param ch The character to insert.
2283 
2284       @throw std::length_error `size() + 1 > max_size()`
2285   */
2286   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2287   iterator
insert(const_iterator pos,value_type ch)2288   insert(
2289     const_iterator pos,
2290     value_type ch)
2291   {
2292     return insert(pos, 1, ch);
2293   }
2294 
2295   /** Insert into the string.
2296 
2297       Inserts `count` copies of `ch` before the character pointed by `pos`.
2298 
2299       @par Precondition
2300 
2301       `pos` shall be valid within `{data(), data() + size()}`
2302 
2303       @par Exception Safety
2304 
2305       Strong guarantee.
2306 
2307       @note All references, pointers, or iterators
2308       referring to contained elements are invalidated. Any
2309       past-the-end iterators are also invalidated.
2310 
2311       @return An iterator which refers to the first inserted character
2312       or `pos` if no characters were inserted
2313 
2314       @param pos The position to insert at.
2315       @param count The number of characters to insert.
2316       @param ch The character to insert.
2317 
2318       @throw std::length_error `size() + count > max_size()`
2319   */
2320   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2321   iterator
2322   insert(
2323     const_iterator pos,
2324     size_type count,
2325     value_type ch);
2326 
2327   /** Insert into the string.
2328 
2329       Inserts characters from the range `{first, last)` before the
2330       character pointed to by `pos`.
2331 
2332       @par Precondition
2333 
2334       `pos` shall be valid within `{data(), data() + size()}`,
2335 
2336       `{first, last)` shall be a valid range
2337 
2338       @par Exception Safety
2339 
2340       Strong guarantee.
2341 
2342       @note All references, pointers, or iterators
2343       referring to contained elements are invalidated. Any
2344       past-the-end iterators are also invalidated.
2345 
2346       @tparam InputIterator The type of the iterators.
2347 
2348       @par Constraints
2349 
2350       `InputIterator` satisfies __InputIterator__ and does not
2351       satisfy __ForwardIterator__.
2352 
2353       @return An iterator which refers to the first inserted character
2354       or `pos` if no characters were inserted
2355 
2356       @param pos The position to insert at.
2357       @param first An iterator representing the first character to insert.
2358       @param last An iterator representing one past the last character to insert.
2359 
2360       @throw std::length_error `size() + insert_count > max_size()`
2361   */
2362   template<typename InputIterator>
2363   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2364 #ifdef BOOST_STATIC_STRING_DOCS
2365   iterator
2366 #else
2367   typename std::enable_if<
2368     detail::is_input_iterator<
2369       InputIterator>::value &&
2370         !detail::is_forward_iterator<
2371           InputIterator>::value, iterator>::type
2372 #endif
2373   insert(
2374     const_iterator pos,
2375     InputIterator first,
2376     InputIterator last);
2377 
2378 #ifndef BOOST_STATIC_STRING_DOCS
2379   template<typename ForwardIterator>
2380   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2381   typename std::enable_if<
2382     detail::is_forward_iterator<
2383       ForwardIterator>::value,
2384         iterator>::type
2385   insert(
2386     const_iterator pos,
2387     ForwardIterator first,
2388     ForwardIterator last);
2389 #endif
2390 
2391   /** Insert into the string.
2392 
2393       Inserts characters from `ilist` before `pos`.
2394 
2395       @par Precondition
2396 
2397       `pos` shall be valid within `{data(), data() + size()}`
2398 
2399       @par Exception Safety
2400 
2401       Strong guarantee.
2402 
2403       @note All references, pointers, or iterators
2404       referring to contained elements are invalidated. Any
2405       past-the-end iterators are also invalidated.
2406 
2407       @return An iterator which refers to the first inserted character
2408       or `pos` if no characters were inserted
2409 
2410       @param pos The position to insert at.
2411       @param ilist The initializer list from which to insert.
2412 
2413       @throw std::length_error `size() + ilist.size() > max_size()`
2414   */
2415   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2416   iterator
insert(const_iterator pos,std::initializer_list<value_type> ilist)2417   insert(
2418     const_iterator pos,
2419     std::initializer_list<value_type> ilist)
2420   {
2421     return insert_unchecked(pos, ilist.begin(), ilist.size());
2422   }
2423 
2424   /** Insert into the string.
2425 
2426       Constructs a temporary `string_view_type` object `sv` from `t` and
2427       inserts `{sv.begin(), sv.end())` at `index`.
2428 
2429       @par Precondition
2430 
2431       `index` shall be valid within `{data(), data() + size()}`
2432 
2433       @par Exception Safety
2434 
2435       Strong guarantee.
2436 
2437       @note All references, pointers, or iterators
2438       referring to contained elements are invalidated. Any
2439       past-the-end iterators are also invalidated.
2440 
2441       @return `*this`
2442 
2443       @tparam T The type of the object to convert.
2444 
2445       @par Constraints
2446 
2447       `std::is_convertible<const T&, string_view>::value &&
2448       !std::is_convertible<const T&, const CharT*>::value`.
2449 
2450       @param index The index to insert at.
2451       @param t The string to insert from.
2452 
2453       @throw std::length_error `size() + sv.size() > max_size()`
2454       @throw std::out_of_range `index > size()`
2455   */
2456   template<typename T
2457 #ifndef BOOST_STATIC_STRING_DOCS
2458     , typename = detail::enable_if_viewable_t<T, CharT, Traits>
2459 #endif
2460   >
2461   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2462   basic_static_string&
insert(size_type index,const T & t)2463   insert(
2464     size_type index,
2465     const T& t)
2466   {
2467     const string_view_type sv = t;
2468     return insert(index, sv.data(), sv.size());
2469   }
2470 
2471   /** Insert into the string.
2472 
2473       Constructs a temporary `string_view_type` object `sv` from `t`
2474       and inserts `sv.substr(index_str, count)` at `index`.
2475 
2476       @par Exception Safety
2477 
2478       Strong guarantee.
2479 
2480       @note All references, pointers, or iterators
2481       referring to contained elements are invalidated. Any
2482       past-the-end iterators are also invalidated.
2483 
2484       @tparam T The type of the object to convert.
2485 
2486       @par Constraints
2487 
2488       `std::is_convertible<const T&, string_view>::value &&
2489       !std::is_convertible<const T&, const_pointer>::value`.
2490 
2491       @return `*this`
2492 
2493       @param index The index to insert at.
2494       @param t The string to insert from.
2495       @param index_str The index in the temporary `string_view_type` object
2496       to start the substring from.
2497       @param count The number of characters to insert.
2498 
2499       @throw std::length_error `size() + sv.size() > max_size()`
2500       @throw std::out_of_range `index > size()`
2501       @throw std::out_of_range `index_str > sv.size()`
2502   */
2503   template<typename T
2504 #ifndef BOOST_STATIC_STRING_DOCS
2505     , typename = detail::enable_if_viewable_t<T, CharT, Traits>
2506 #endif
2507   >
2508   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2509   basic_static_string&
insert(size_type index,const T & t,size_type index_str,size_type count=npos)2510   insert(
2511     size_type index,
2512     const T& t,
2513     size_type index_str,
2514     size_type count = npos)
2515   {
2516     const auto sv = string_view_type(t).substr(index_str, count);
2517     return insert(index, sv.data(), sv.size());
2518   }
2519 
2520   /** Erase from the string.
2521 
2522       Erases `num` characters from the string, starting at `index`.
2523       `num` is determined as the smaller of `count` and `size() - index`.
2524 
2525       @par Exception Safety
2526 
2527       Strong guarantee.
2528 
2529       @note All references, pointers, or iterators
2530       referring to contained elements are invalidated. Any
2531       past-the-end iterators are also invalidated.
2532 
2533       @return `*this`
2534 
2535       @param index The index to erase at.
2536       The default argument for this parameter is `0`.
2537 
2538       @param count The number of characters to erase.
2539       The default argument for this parameter is @ref npos.
2540 
2541       @throw std::out_of_range `index > size()`
2542   */
2543   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2544   basic_static_string&
erase(size_type index=0,size_type count=npos)2545   erase(
2546     size_type index = 0,
2547     size_type count = npos)
2548   {
2549     erase(data() + index, data() + index + capped_length(index, count));
2550     return *this;
2551   }
2552 
2553   /** Erase from the string.
2554 
2555       Erases the character at `pos`.
2556 
2557       @par Preconditions
2558 
2559       `pos` shall be valid within `{data(), data() + size()}`
2560 
2561       @par Exception Safety
2562 
2563       Strong guarantee.
2564 
2565       @note All references, pointers, or iterators
2566       referring to contained elements are invalidated. Any
2567       past-the-end iterators are also invalidated.
2568 
2569       @return An iterator referring to character immediately following
2570       the erased character, or @ref end() if one does not exist.
2571 
2572       @param pos An iterator referring to the character to erase.
2573   */
2574   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2575   iterator
erase(const_iterator pos)2576   erase(const_iterator pos)
2577   {
2578     BOOST_STATIC_STRING_ASSERT(!empty());
2579     return erase(pos, pos + 1);
2580   }
2581 
2582   /** Erase from the string.
2583 
2584       Erases the characters in the range `{first, last)`.
2585 
2586       @par Precondition
2587 
2588       `{first, last}` shall be valid within `{data(), data() + size()}`
2589 
2590       @par Exception Safety
2591 
2592       Strong guarantee.
2593 
2594       @note All references, pointers, or iterators
2595       referring to contained elements are invalidated. Any
2596       past-the-end iterators are also invalidated.
2597 
2598       @return An iterator referring to the character `last`
2599       previously referred to, or @ref end() if one does not exist.
2600 
2601       @param first An iterator referring to the first character to erase.
2602 
2603       @param last An iterator past the last character to erase.
2604   */
2605   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2606   iterator
2607   erase(
2608     const_iterator first,
2609     const_iterator last);
2610 
2611   /** Append a character.
2612 
2613       Appends a character to the end of the string.
2614 
2615       @par Exception Safety
2616 
2617       Strong guarantee.
2618 
2619       @param ch The character to append.
2620 
2621       @throw std::length_error `size() >= max_size()`
2622   */
2623   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2624   void
2625   push_back(value_type ch);
2626 
2627   /** Remove the last character.
2628 
2629       Removes a character from the end of the string.
2630 
2631       @par Precondition
2632 
2633       `not empty()`
2634   */
2635   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2636   void
pop_back()2637   pop_back() noexcept
2638   {
2639     BOOST_STATIC_STRING_ASSERT(!empty());
2640     this->set_size(size() - 1);
2641     term();
2642   }
2643 
2644   /** Append to the string.
2645 
2646       Appends `count` copies of `ch` to the end of the string.
2647 
2648       @par Exception Safety
2649 
2650       Strong guarantee.
2651 
2652       @return `*this`
2653 
2654       @param count The number of characters to append.
2655 
2656       @param ch The character to append.
2657 
2658       @throw std::length_error `size() + count > max_size()`
2659   */
2660   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2661   basic_static_string&
2662   append(
2663     size_type count,
2664     value_type ch);
2665 
2666   /** Append to the string.
2667 
2668       Appends `s` to the end of the string.
2669 
2670       @par Exception Safety
2671 
2672       Strong guarantee.
2673 
2674       @tparam M The size of the string to append.
2675 
2676       @return `*this`
2677 
2678       @param s The string to append.
2679 
2680       @throw std::length_error `size() + s.size() > max_size()`
2681   */
2682   template<std::size_t M>
2683   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2684   basic_static_string&
append(const basic_static_string<M,CharT,Traits> & s)2685   append(
2686     const basic_static_string<M, CharT, Traits>& s)
2687   {
2688     return append(s.data(), s.size());
2689   }
2690 
2691   /** Append to the string.
2692 
2693       Appends the substring `sub` to the end of the string,
2694       where `sub` is `s.substr(pos, count)`.
2695 
2696       @par Exception Safety
2697 
2698       Strong guarantee.
2699 
2700       @tparam M The size of the string to append.
2701 
2702       @return `*this`
2703 
2704       @param s The string to append.
2705 
2706       @param pos The index at which to begin the substring.
2707 
2708       @param count The size of the substring. The default
2709       argument for this parameter is @ref npos.
2710 
2711       @throw std::length_error `size() + sub.size() > max_size()`
2712       @throw std::out_of_range `pos > s.size()`
2713   */
2714   template<std::size_t M>
2715   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2716   basic_static_string&
append(const basic_static_string<M,CharT,Traits> & s,size_type pos,size_type count=npos)2717   append(
2718     const basic_static_string<M, CharT, Traits>& s,
2719     size_type pos,
2720     size_type count = npos)
2721   {
2722     return append(s.data() + pos, s.capped_length(pos, count));
2723   }
2724 
2725   /** Append to the string.
2726 
2727       Appends `count` characters from the string pointed
2728       to by `s` to the end of the string.
2729 
2730       @par Exception Safety
2731 
2732       Strong guarantee.
2733 
2734       @note The string can contain null characters.
2735 
2736       @return `*this`
2737 
2738       @param s The string to append.
2739 
2740       @param count The number of characters to append.
2741 
2742       @throw std::length_error `size() + count > max_size()`
2743   */
2744   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2745   basic_static_string&
2746   append(
2747     const_pointer s,
2748     size_type count);
2749 
2750   /** Append to the string.
2751 
2752       Appends `count` characters from the string pointed
2753       to by `s` to the end of the string, where `count`
2754       is `traits_type::length(s)`.
2755 
2756       @par Exception Safety
2757 
2758       Strong guarantee.
2759 
2760       @return `*this`
2761 
2762       @param s The string to append.
2763 
2764       @throw std::length_error `size() + count > max_size()`
2765   */
2766   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2767   basic_static_string&
append(const_pointer s)2768   append(const_pointer s)
2769   {
2770     return append(s, traits_type::length(s));
2771   }
2772 
2773   // KRYSTIAN TODO: change exception safety
2774   /** Append to the string.
2775 
2776       Appends characters from the range `{first, last)`
2777       to the end of the string.
2778 
2779       @par Precondition
2780 
2781       `{first, last)` shall be a valid range
2782 
2783       @par Exception Safety
2784 
2785       Strong guarantee.
2786 
2787       @tparam InputIterator The type of the iterators.
2788 
2789       @par Constraints
2790 
2791       `InputIterator` satisfies __InputIterator__.
2792 
2793       @return `*this`
2794 
2795       @param first An iterator referring to the
2796       first character to append.
2797 
2798       @param last An iterator past the end of
2799       last character to append.
2800 
2801       @throw std::length_error `size() + std::distance(first, last) > max_size()`
2802   */
2803   template<typename InputIterator>
2804   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2805 #ifdef BOOST_STATIC_STRING_DOCS
2806   basic_static_string&
2807 #else
2808   typename std::enable_if<
2809     detail::is_input_iterator<InputIterator>::value,
2810       basic_static_string&>::type
2811 #endif
append(InputIterator first,InputIterator last)2812   append(
2813     InputIterator first,
2814     InputIterator last)
2815   {
2816     this->set_size(size() + read_back(true, first, last));
2817     return term();
2818   }
2819 
2820   /** Append to the string.
2821 
2822       Appends the characters from `ilist` to the
2823       end of the string.
2824 
2825       @par Exception Safety
2826 
2827       Strong guarantee.
2828 
2829       @return `*this`
2830 
2831       @param ilist The initializer list to append.
2832 
2833       @throw std::length_error `size() + ilist.size() > max_size()`
2834   */
2835   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2836   basic_static_string&
append(std::initializer_list<value_type> ilist)2837   append(
2838     std::initializer_list<value_type> ilist)
2839   {
2840     return append(ilist.begin(), ilist.size());
2841   }
2842 
2843   /** Append to the string.
2844 
2845       Appends `sv` to the end of the string,
2846       where `sv` is `string_view_type(t)`.
2847 
2848       @par Exception Safety
2849 
2850       Strong guarantee.
2851 
2852       @tparam T The type of the object to convert.
2853 
2854       @par Constraints
2855 
2856       @code
2857       std::is_convertible<T const&, string_view>::value &&
2858       !std::is_convertible<T const&, char const*>::value
2859       @endcode
2860 
2861       @return `*this`
2862 
2863       @param t The string to append.
2864 
2865       @throw std::length_error `size() + sv.size() > max_size()`
2866   */
2867   template<typename T
2868 #ifndef BOOST_STATIC_STRING_DOCS
2869     , typename = detail::enable_if_viewable_t<T, CharT, Traits>
2870 #endif
2871   >
2872   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2873   basic_static_string&
append(const T & t)2874   append(const T& t)
2875   {
2876     const string_view_type sv = t;
2877     return append(sv.data(), sv.size());
2878   }
2879 
2880   /** Append to the string.
2881 
2882       Appends the substring `sv` to the end of the string,
2883       where `sv` is `string_view_type(t).substr(pos, count)`.
2884 
2885       @par Exception Safety
2886 
2887       Strong guarantee.
2888 
2889       @tparam T The type of the object to convert.
2890 
2891       @par Constraints
2892 
2893       @code
2894       std::is_convertible<T const&, string_view>::value &&
2895       !std::is_convertible<T const&, char const*>::value
2896       @endcode
2897 
2898       @return `*this`
2899 
2900       @param t The object to append.
2901 
2902       @param pos The index at which to begin the substring.
2903 
2904       @param count The size of the substring. The default
2905       argument for this parameter is @ref npos.
2906 
2907       @throw std::length_error `size() + sv.size() > max_size()`
2908   */
2909   template<typename T
2910 #ifndef BOOST_STATIC_STRING_DOCS
2911     , typename = detail::enable_if_viewable_t<T, CharT, Traits>
2912 #endif
2913   >
2914   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2915   basic_static_string&
append(const T & t,size_type pos,size_type count=npos)2916   append(
2917     const T& t,
2918     size_type pos,
2919     size_type count = npos)
2920   {
2921     const auto sv = string_view_type(t).substr(pos, count);
2922     return append(sv.data(), sv.size());
2923   }
2924 
2925   /** Append to the string.
2926 
2927       Appends `s` to the end of the string.
2928 
2929       @par Exception Safety
2930 
2931       Strong guarantee.
2932 
2933       @tparam M The size of the string to append.
2934 
2935       @return `*this`
2936 
2937       @param s The string to append.
2938 
2939       @throw std::length_error `size() + s.size() > max_size()`
2940   */
2941   template<std::size_t M>
2942   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2943   basic_static_string&
operator +=(const basic_static_string<M,CharT,Traits> & s)2944   operator+=(
2945     const basic_static_string<M, CharT, Traits>& s)
2946   {
2947     return append(s);
2948   }
2949 
2950   /** Append to the string.
2951 
2952       Appends a character to the end of the string.
2953 
2954       @par Exception Safety
2955 
2956       Strong guarantee.
2957 
2958       @param ch The character to append.
2959 
2960       @throw std::length_error `size() >= max_size()`
2961   */
2962   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2963   basic_static_string&
operator +=(value_type ch)2964   operator+=(value_type ch)
2965   {
2966     push_back(ch);
2967     return *this;
2968   }
2969 
2970   /** Append to the string.
2971 
2972       Appends `count` characters from the string pointed
2973       to by `s` to the end of the string, where `count`
2974       is `traits_type::length(s)`.
2975 
2976       @par Exception Safety
2977 
2978       Strong guarantee.
2979 
2980       @return `*this`
2981 
2982       @param s The string to append.
2983 
2984       @throw std::length_error `size() + count > max_size()`
2985   */
2986   BOOST_STATIC_STRING_CPP14_CONSTEXPR
2987   basic_static_string&
operator +=(const_pointer s)2988   operator+=(const_pointer s)
2989   {
2990     return append(s);
2991   }
2992 
2993   /** Append to the string.
2994 
2995       Appends the characters from `ilist` to the
2996       end of the string.
2997 
2998       @par Exception Safety
2999 
3000       Strong guarantee.
3001 
3002       @return `*this`
3003 
3004       @param ilist The initializer list to append.
3005 
3006       @throw std::length_error `size() + ilist.size() > max_size()`
3007   */
3008   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3009   basic_static_string&
operator +=(std::initializer_list<value_type> ilist)3010   operator+=(
3011     std::initializer_list<value_type> ilist)
3012   {
3013     return append(ilist);
3014   }
3015 
3016   /** Append to the string.
3017 
3018       Appends `sv` to the end of the string,
3019       where `sv` is `string_view_type(t)`.
3020 
3021       @par Exception Safety
3022 
3023       Strong guarantee.
3024 
3025       @tparam T The type of the object to convert.
3026 
3027       @par Constraints
3028 
3029       @code
3030       std::is_convertible<T const&, string_view>::value &&
3031       !std::is_convertible<T const&, char const*>::value
3032       @endcode
3033 
3034       @return `*this`
3035 
3036       @param t The string to append.
3037 
3038       @throw std::length_error `size() + sv.size() > max_size()`
3039   */
3040   template<typename T
3041 #ifndef BOOST_STATIC_STRING_DOCS
3042     , typename = detail::enable_if_viewable_t<T, CharT, Traits>
3043 #endif
3044   >
3045   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3046   basic_static_string&
operator +=(const T & t)3047   operator+=(const T& t)
3048   {
3049     return append(t);
3050   }
3051 
3052   /** Compare a string with the string.
3053 
3054       Let `comp` be `traits_type::compare(data(), s.data(), std::min(size(), s.size())`.
3055       If `comp != 0`, then the result is `comp`. Otherwise, the result is
3056       `0` if `size() == s.size()`, `-1` if `size() < s.size()`, and `1`
3057       otherwise.
3058 
3059       @par Complexity
3060       Linear.
3061 
3062       @return The result of lexicographically comparing `s` and the string.
3063 
3064       @tparam M The size of the string to compare with.
3065 
3066       @param s The string to compare.
3067   */
3068   template<std::size_t M>
3069   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3070   int
compare(const basic_static_string<M,CharT,Traits> & s) const3071   compare(
3072     const basic_static_string<M, CharT, Traits>& s) const noexcept
3073   {
3074     return detail::lexicographical_compare<CharT, Traits>(
3075       data(), size(), s.data(), s.size());
3076   }
3077 
3078   /** Compare a string with the string.
3079 
3080     Let `sub` be `substr(pos1, count1)` and `comp` be
3081     `traits_type::compare(sub.data(), s.data(), std::min(sub.size(), s.size())`.
3082     If `comp != 0`, then the result is `comp`. Otherwise, the result is
3083     `0` if `sub.size() == s.size()`, `-1` if `sub.size() < s.size()`, and `1`
3084     otherwise.
3085 
3086     @par Complexity
3087 
3088     Linear.
3089 
3090     @par Exception Safety
3091 
3092     Strong guarantee.
3093 
3094     @return The result of lexicographically comparing `sub` and `s`.
3095 
3096     @tparam M The size of the string to compare with.
3097 
3098     @param pos1 The index at which to begin the substring.
3099 
3100     @param count1 The size of the substring.
3101 
3102     @param s The string to compare.
3103 
3104     @throw std::out_of_range `pos1 > size()`
3105     */
3106   template<std::size_t M>
3107   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3108   int
compare(size_type pos1,size_type count1,const basic_static_string<M,CharT,Traits> & s) const3109   compare(
3110     size_type pos1,
3111     size_type count1,
3112     const basic_static_string<M, CharT, Traits>& s) const
3113   {
3114     return detail::lexicographical_compare<CharT, Traits>(
3115       data() + pos1, capped_length(pos1, count1), s.data(), s.size());
3116   }
3117 
3118   /** Compare a string with the string.
3119 
3120       Let `sub1` be `substr(pos1, count1)`, `sub2` be
3121       `s.substr(pos2, count2)`, and `comp` be
3122       `traits_type::compare(sub1.data(), sub2.data(), std::min(sub1.size(), sub2.size())`.
3123       If `comp != 0`, then the result is `comp`. Otherwise, the result is
3124       `0` if `sub1.size() == sub2.size()`, `-1` if `sub1.size() < sub2.size()`, and `1`
3125       otherwise.
3126 
3127       @par Complexity
3128 
3129       Linear.
3130 
3131       @par Exception Safety
3132 
3133       Strong guarantee.
3134 
3135       @return The result of lexicographically comparing `sub1` and `sub2`.
3136 
3137       @param pos1 The index at which to begin the substring.
3138 
3139       @param count1 The size of the substring.
3140 
3141       @param s The string to compare.
3142 
3143       @param pos2 The index at which to begin the substring to compare.
3144 
3145       @param count2 The size of the substring to compare.
3146 
3147       @throw std::out_of_range `pos1 > size()`
3148 
3149       @throw std::out_of_range `pos2 > s.size()`
3150   */
3151   template<std::size_t M>
3152   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3153   int
compare(size_type pos1,size_type count1,const basic_static_string<M,CharT,Traits> & s,size_type pos2,size_type count2=npos) const3154   compare(
3155     size_type pos1,
3156     size_type count1,
3157     const basic_static_string<M, CharT, Traits>& s,
3158     size_type pos2,
3159     size_type count2 = npos) const
3160   {
3161     return detail::lexicographical_compare<CharT, Traits>(
3162       data() + pos1, capped_length(pos1, count1),
3163       s.data() + pos2, s.capped_length(pos2, count2));
3164   }
3165 
3166   /** Compare a string with the string.
3167 
3168       Let `len` be `traits_type::length(s)` and `comp` be
3169       `traits_type::compare(data(), s, std::min(size(), len)`.
3170       If `comp != 0`, then the result is `comp`. Otherwise, the result is
3171       `0` if `size() == len`, `-1` if `size() < len`, and `1`
3172       otherwise.
3173 
3174       @par Complexity
3175 
3176       Linear.
3177 
3178       @return The result of lexicographically comparing `s` and the string.
3179 
3180       @param s The string to compare.
3181   */
3182   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3183   int
compare(const_pointer s) const3184   compare(const_pointer s) const noexcept
3185   {
3186     return detail::lexicographical_compare<CharT, Traits>(
3187       data(), size(), s, traits_type::length(s));
3188   }
3189 
3190   /** Compare a string with the string.
3191 
3192       Let `sub` be `substr(pos1, count1)`, `len` be
3193       `traits_type::length(s)`, and `comp` be
3194       `traits_type::compare(sub.data(), s, std::min(size(), len)`.
3195       If `comp != 0`, then the result is `comp`. Otherwise, the result is
3196       `0` if `sub.size() == len`, `-1` if `sub.size() < len`, and `1`
3197       otherwise.
3198 
3199       @par Complexity
3200 
3201       Linear.
3202 
3203       @par Exception Safety
3204 
3205       Strong guarantee.
3206 
3207       @return The result of lexicographically comparing `s` and `sub`.
3208 
3209       @param pos1 The index at which to begin the substring.
3210 
3211       @param count1 The size of the substring.
3212 
3213       @param s The string to compare.
3214 
3215       @throw std::out_of_range `pos1 > size()`
3216   */
3217   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3218   int
compare(size_type pos1,size_type count1,const_pointer s) const3219   compare(
3220     size_type pos1,
3221     size_type count1,
3222     const_pointer s) const
3223   {
3224     return detail::lexicographical_compare<CharT, Traits>(
3225       data() + pos1, capped_length(pos1, count1), s, traits_type::length(s));
3226   }
3227 
3228   /** Compare a string with the string.
3229 
3230       Let `sub` be `substr(pos1, count1)`, and `comp` be
3231       `traits_type::compare(sub.data(), s, std::min(size(), count2)`.
3232       If `comp != 0`, then the result is `comp`. Otherwise, the result is
3233       `0` if `sub.size() == count2`, `-1` if `sub.size() < count2`, and `1`
3234       otherwise.
3235 
3236       @par Complexity
3237 
3238       Linear.
3239 
3240       @par Exception Safety
3241 
3242       Strong guarantee.
3243 
3244       @return The result of lexicographically comparing `s` and `sub`.
3245 
3246       @param pos1 The index at which to begin the substring.
3247 
3248       @param count1 The size of the substring.
3249 
3250       @param s The string to compare.
3251 
3252       @param count2 The length of the string to compare.
3253 
3254       @throw std::out_of_range `pos1 > size()`
3255   */
3256   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3257   int
compare(size_type pos1,size_type count1,const_pointer s,size_type count2) const3258   compare(
3259     size_type pos1,
3260     size_type count1,
3261     const_pointer s,
3262     size_type count2) const
3263   {
3264     return detail::lexicographical_compare<CharT, Traits>(
3265       data() + pos1, capped_length(pos1, count1), s, count2);
3266   }
3267 
3268   /** Compare a string with the string.
3269 
3270       Let `s` be `string_view_type(t)` and `comp` be
3271       `traits_type::compare(data(), s.data(), std::min(size(), s.size())`.
3272       If `comp != 0`, then the result is `comp`. Otherwise, the result is
3273       `0` if `size() == s.size()`, `-1` if `size() < s.size()`, and `1`
3274       otherwise.
3275 
3276       @par Complexity
3277 
3278       Linear.
3279 
3280       @par Exception Safety
3281 
3282       Strong guarantee.
3283 
3284       @tparam T The type of the object to convert.
3285 
3286       @par Constraints
3287 
3288       @code
3289       std::is_convertible<const T&, string_view>::value &&
3290       !std::is_convertible<const T&, const_pointer>::value.
3291       @endcode
3292 
3293       @return The result of lexicographically comparing `s` and the string.
3294 
3295       @param t The string to compare.
3296   */
3297   template<typename T
3298 #ifndef BOOST_STATIC_STRING_DOCS
3299     , typename = detail::enable_if_viewable_t<T, CharT, Traits>
3300 #endif
3301   >
3302   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3303   int
compare(const T & t) const3304   compare(const T& t) const noexcept
3305   {
3306     const string_view_type sv = t;
3307     return detail::lexicographical_compare<CharT, Traits>(
3308       data(), size(), sv.data(), sv.size());
3309   }
3310 
3311   /** Compare a string with the string.
3312 
3313       Let `s` be `string_view_type(t)`, `sub` be
3314       `substr(pos1, count1)`, and `comp` be
3315       `traits_type::compare(sub.data(), s.data(), std::min(sub.size(), s.size())`.
3316       If `comp != 0`, then the result is `comp`. Otherwise, the result is
3317       `0` if `sub.size() == s.size()`, `-1` if `sub.size() < s.size()`, and `1`
3318       otherwise.
3319 
3320       @par Complexity
3321 
3322       Linear.
3323 
3324       @par Exception Safety
3325 
3326       Strong guarantee.
3327 
3328       @tparam T The type of the object to convert.
3329 
3330       @par Constraints
3331 
3332       @code
3333       std::is_convertible<const T&, string_view>::value &&
3334       !std::is_convertible<const T&, const_pointer>::value.
3335       @endcode
3336 
3337       @return The result of lexicographically comparing `s` and `sub`.
3338 
3339       @param pos1 The index at which to begin the substring.
3340 
3341       @param count1 The length of the substring.
3342 
3343       @param t The string to compare.
3344   */
3345   template<typename T
3346 #ifndef BOOST_STATIC_STRING_DOCS
3347     , typename = detail::enable_if_viewable_t<T, CharT, Traits>
3348 #endif
3349   >
3350   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3351   int
compare(size_type pos1,size_type count1,const T & t) const3352   compare(
3353     size_type pos1,
3354     size_type count1,
3355     const T& t) const
3356   {
3357     const string_view_type sv = t;
3358     return detail::lexicographical_compare<CharT, Traits>(
3359       data() + pos1, capped_length(pos1, count1), sv.data(), sv.size());
3360   }
3361 
3362   /** Compare a string with the string.
3363 
3364       Let `sub1` be `substr(pos1, count1)`, `sub2` be
3365       `string_view_type(t).substr(pos2, count2)`, and `comp` be
3366       `traits_type::compare(sub1.data(), sub2.data(), std::min(sub1.size(), sub2.size())`.
3367       If `comp != 0`, then the result is `comp`. Otherwise, the result is
3368       `0` if `sub1.size() == sub2.size()`, `-1` if `sub1.size() < sub2.size()`, and `1`
3369       otherwise.
3370 
3371       @par Complexity
3372 
3373       Linear.
3374 
3375       @par Exception Safety
3376 
3377       Strong guarantee.
3378 
3379       @tparam T The type of the object to convert.
3380 
3381       @par Constraints
3382 
3383       @code
3384       std::is_convertible<const T&, string_view>::value &&
3385       !std::is_convertible<const T&, const_pointer>::value.
3386       @endcode
3387 
3388       @return The result of lexicographically comparing `sub1` and `sub2`.
3389 
3390       @param pos1 The index at which to begin the substring in the string.
3391 
3392       @param count1 The length of the substring in the string.
3393 
3394       @param t The string to compare.
3395 
3396       @param pos2 The index at which to begin the substring in the string view.
3397 
3398       @param count2 The length of the substring in the string view.
3399   */
3400   template<typename T
3401 #ifndef BOOST_STATIC_STRING_DOCS
3402     , typename = detail::enable_if_viewable_t<T, CharT, Traits>
3403 #endif
3404   >
3405   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3406   int
compare(size_type pos1,size_type count1,const T & t,size_type pos2,size_type count2=npos) const3407   compare(
3408     size_type pos1,
3409     size_type count1,
3410     const T& t,
3411     size_type pos2,
3412     size_type count2 = npos) const
3413   {
3414     const auto sv = string_view_type(t).substr(pos2, count2);
3415     return compare(pos1, count1,
3416       sv.data(), sv.size());
3417   }
3418 
3419   /** Return a substring.
3420 
3421       Returns a substring of the string.
3422 
3423       @par Exception Safety
3424 
3425       Strong guarantee.
3426 
3427       @return A string object containing the characters
3428       `{data() + pos, std::min(count, size() - pos))`.
3429 
3430       @param pos The index to being the substring at. The
3431       default arugment for this parameter is `0`.
3432       @param count The length of the substring. The default arugment
3433       for this parameter is @ref npos.
3434 
3435       @throw std::out_of_range `pos > size()`
3436   */
3437 #ifndef BOOST_STATIC_STRING_GCC5_BAD_CONSTEXPR
3438   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3439 #endif
3440   basic_static_string
substr(size_type pos=0,size_type count=npos) const3441   substr(
3442     size_type pos = 0,
3443     size_type count = npos) const
3444   {
3445     return basic_static_string(
3446       data() + pos, capped_length(pos, count));
3447   }
3448 
3449   /** Return a string view of a substring.
3450 
3451       Returns a view of a substring.
3452 
3453       @par Exception Safety
3454 
3455       Strong guarantee.
3456 
3457       @return A `string_view_type` object referring
3458       to `{data() + pos, std::min(count, size() - pos))`.
3459 
3460       @param pos The index to being the substring at. The
3461       default arugment for this parameter is `0`.
3462       @param count The length of the substring. The default arugment
3463       for this parameter is @ref npos.
3464 
3465       @throw std::out_of_range `pos > size()`
3466   */
3467   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3468   string_view_type
subview(size_type pos=0,size_type count=npos) const3469   subview(
3470     size_type pos = 0,
3471     size_type count = npos) const
3472   {
3473     return string_view_type(
3474       data() + pos, capped_length(pos, count));
3475   }
3476 
3477   /** Copy a substring to another string.
3478 
3479       Copies `std::min(count, size() - pos)` characters starting at
3480       index `pos` to the string pointed to by `dest`.
3481 
3482       @note The resulting string is not null terminated.
3483 
3484       @return The number of characters copied.
3485 
3486       @param count The number of characters to copy.
3487       @param dest The string to copy to.
3488       @param pos The index to begin copying from. The
3489       default argument for this parameter is `0`.
3490 
3491       @throw std::out_of_range `pos > max_size()`
3492   */
3493   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3494   size_type
copy(pointer dest,size_type count,size_type pos=0) const3495   copy(
3496     pointer dest,
3497     size_type count,
3498     size_type pos = 0) const
3499   {
3500     const auto num_copied = capped_length(pos, count);
3501     traits_type::copy(dest, data() + pos, num_copied);
3502     return num_copied;
3503   }
3504 
3505   /** Change the size of the string.
3506 
3507       Resizes the string to contain `n` characters. If
3508       `n > size()`, characters with the value `CharT()` are
3509       appended. Otherwise, `size()` is reduced to `n`.
3510 
3511       @param n The size to resize the string to.
3512 
3513       @throw std::out_of_range `n > max_size()`
3514   */
3515   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3516   void
resize(size_type n)3517   resize(size_type n)
3518   {
3519     resize(n, value_type());
3520   }
3521 
3522   /** Change the size of the string.
3523 
3524       Resizes the string to contain `n` characters. If
3525       `n > size()`, copies of `c` are
3526       appended. Otherwise, `size()` is reduced to `n`.
3527 
3528       @param n The size to resize the string to.
3529       @param c The characters to append if the size
3530       increases.
3531 
3532       @throw std::out_of_range `n > max_size()`
3533   */
3534   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3535   void
3536   resize(
3537     size_type n,
3538     value_type c);
3539 
3540   /** Swap two strings.
3541 
3542       Swaps the contents of the string and `s`.
3543 
3544       @par Exception Safety
3545 
3546       Strong guarantee.
3547 
3548       @note
3549 
3550       All references, pointers, or iterators
3551       referring to contained elements are invalidated. Any
3552       past-the-end iterators are also invalidated.
3553 
3554       @param s The string to swap with.
3555   */
3556   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3557   void
3558   swap(basic_static_string& s) noexcept;
3559 
3560   /** Swap two strings.
3561 
3562       Swaps the contents of the string and `s`.
3563 
3564       @par Exception Safety
3565 
3566       Strong guarantee.
3567 
3568       @note
3569 
3570       All references, pointers, or iterators
3571       referring to contained elements are invalidated. Any
3572       past-the-end iterators are also invalidated.
3573 
3574       @tparam M The size of the string to swap with.
3575 
3576       @param s The string to swap with.
3577 
3578       @throw std::length_error `s.size() > max_size() || size() > s.max_size()`
3579   */
3580   template<std::size_t M>
3581   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3582   void
3583   swap(basic_static_string<M, CharT, Traits>& s);
3584 
3585   /** Replace a part of the string.
3586 
3587       Replaces `rcount` characters starting at index `pos1` with those
3588       of `str`, where `rcount` is `std::min(n1, size() - pos1)`.
3589 
3590       @par Exception Safety
3591 
3592       Strong guarantee.
3593 
3594       @note The replacement is done unchecked when
3595       the capacity of `str` differs from that of the
3596       string the function is called on.
3597 
3598       All references, pointers, or iterators
3599       referring to contained elements are invalidated. Any
3600       past-the-end iterators are also invalidated.
3601 
3602       @tparam M The size of the input string.
3603 
3604       @return `*this`
3605 
3606       @param pos1 The index to replace at.
3607       @param n1 The number of characters to replace.
3608       @param str The string to replace with.
3609 
3610       @throw std::length_error `size() + (str.size() - rcount) > max_size()`
3611       @throw std::out_of_range `pos1 > size()`
3612   */
3613   template<size_t M>
3614   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3615   basic_static_string&
replace(size_type pos1,size_type n1,const basic_static_string<M,CharT,Traits> & str)3616   replace(
3617     size_type pos1,
3618     size_type n1,
3619     const basic_static_string<M, CharT, Traits>& str)
3620   {
3621     return replace_unchecked(pos1, n1, str.data(), str.size());
3622   }
3623 
3624 #ifndef BOOST_STATIC_STRING_DOCS
3625   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3626   basic_static_string&
replace(size_type pos1,size_type n1,const basic_static_string & str)3627   replace(
3628     size_type pos1,
3629     size_type n1,
3630     const basic_static_string& str)
3631   {
3632     return replace(pos1, n1, str.data(), str.size());
3633   }
3634 #endif
3635 
3636   /** Replace a part of the string.
3637 
3638       Replaces `rcount` characters starting at index `pos1` with those of
3639       `str.subview(pos2, n2)`, where `rcount` is `std::min(n1, size() - pos1)`.
3640 
3641       @par Exception Safety
3642 
3643       Strong guarantee.
3644 
3645       @note The replacement is done unchecked when
3646       the capacity of `str` differs from that of the
3647       string the function is called on.
3648 
3649       All references, pointers, or iterators
3650       referring to contained elements are invalidated. Any
3651       past-the-end iterators are also invalidated.
3652 
3653       @return `*this`
3654 
3655       @param pos1 The index to replace at.
3656       @param n1 The number of characters to replace.
3657       @param str The string to replace with.
3658       @param pos2 The index to begin the substring.
3659       @param n2 The length of the substring.
3660       The default argument for this parameter is @ref npos.
3661 
3662       @throw std::length_error `size() + (std::min(str.size(), n2) - rcount) > max_size()`
3663       @throw std::out_of_range `pos1 > size()`
3664       @throw std::out_of_range `pos2 > str.size()`
3665   */
3666   template<std::size_t M>
3667   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3668   basic_static_string&
replace(size_type pos1,size_type n1,const basic_static_string<M,CharT,Traits> & str,size_type pos2,size_type n2=npos)3669   replace(
3670     size_type pos1,
3671     size_type n1,
3672     const basic_static_string<M, CharT, Traits>& str,
3673     size_type pos2,
3674     size_type n2 = npos)
3675   {
3676     return replace_unchecked(pos1, n1, str.data() + pos2, str.capped_length(pos2, n2));
3677   }
3678 
3679 #ifndef BOOST_STATIC_STRING_DOCS
3680   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3681   basic_static_string&
replace(size_type pos1,size_type n1,const basic_static_string & str,size_type pos2,size_type n2=npos)3682   replace(
3683     size_type pos1,
3684     size_type n1,
3685     const basic_static_string& str,
3686     size_type pos2,
3687     size_type n2 = npos)
3688   {
3689     return replace(pos1, n1, str.data() + pos2, str.capped_length(pos2, n2));
3690   }
3691 #endif
3692 
3693   /** Replace a part of the string.
3694 
3695       Constructs a temporary `string_view_type` object `sv` from `t`, and
3696       replaces `rcount` characters starting at index `pos1` with those
3697       of `sv`, where `rcount` is `std::min(n1, size() - pos1)`.
3698 
3699       @par Exception Safety
3700 
3701       Strong guarantee.
3702 
3703       @note All references, pointers, or iterators
3704       referring to contained elements are invalidated. Any
3705       past-the-end iterators are also invalidated.
3706 
3707       @tparam T The type of the object to convert.
3708 
3709       @par Constraints
3710 
3711       `std::is_convertible<const T&, string_view>::value &&
3712       !std::is_convertible<const T&, const CharT*>::value`.
3713 
3714       @return `*this`
3715 
3716       @param pos1 The index to replace at.
3717       @param n1 The number of characters to replace.
3718       @param t The object to replace with.
3719 
3720       @throw std::length_error `size() + (sv.size() - rcount) > max_size()`
3721       @throw std::out_of_range `pos1 > size()`
3722   */
3723   template<typename T
3724 #ifndef BOOST_STATIC_STRING_DOCS
3725     , typename = detail::enable_if_viewable_t<T, CharT, Traits>
3726 #endif
3727   >
3728   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3729   basic_static_string&
replace(size_type pos1,size_type n1,const T & t)3730   replace(
3731     size_type pos1,
3732     size_type n1,
3733     const T& t)
3734   {
3735     const string_view_type sv = t;
3736     return replace(pos1, n1, sv.data(), sv.size());
3737   }
3738 
3739   /** Replace a part of the string.
3740 
3741       Constructs a temporary `string_view_type` object `sv` from `t`, and
3742       replaces `rcount` characters starting at index `pos1` with those
3743       of `sv.substr(pos2, n2)`, where `rcount` is `std::min(n1, size() - pos)`.
3744 
3745       @par Exception Safety
3746 
3747       Strong guarantee.
3748 
3749       @note All references, pointers, or iterators
3750       referring to contained elements are invalidated. Any
3751       past-the-end iterators are also invalidated.
3752 
3753       @tparam T The type of the object to convert.
3754 
3755       @par Constraints
3756 
3757       `std::is_convertible<const T&, string_view>::value &&
3758       !std::is_convertible<const T&, const CharT*>::value`.
3759 
3760       @return `*this`
3761 
3762       @param pos1 The index to replace at.
3763       @param n1 The number of characters to replace.
3764       @param t The object to replace with.
3765       @param pos2 The index to begin the substring.
3766       @param n2 The length of the substring.
3767       The default argument for this parameter is @ref npos.
3768 
3769       @throw std::length_error `size() + (std::min(n2, sv.size()) - rcount) > max_size()`
3770       @throw std::out_of_range `pos1 > size()`
3771       @throw std::out_of_range `pos2 > sv.size()`
3772   */
3773   template<typename T
3774 #ifndef BOOST_STATIC_STRING_DOCS
3775     , typename = detail::enable_if_viewable_t<T, CharT, Traits>
3776 #endif
3777   >
3778   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3779   basic_static_string&
replace(size_type pos1,size_type n1,const T & t,size_type pos2,size_type n2=npos)3780   replace(
3781     size_type pos1,
3782     size_type n1,
3783     const T& t,
3784     size_type pos2,
3785     size_type n2 = npos)
3786   {
3787     const string_view_type sv = t;
3788     return replace(pos1, n1, sv.substr(pos2, n2));
3789   }
3790 
3791   /** Replace a part of the string.
3792 
3793       Replaces `rcount` characters starting at index `pos` with those of
3794       `{s, s + n2)`, where `rcount` is `std::min(n1, size() - pos)`.
3795 
3796       @par Exception Safety
3797 
3798       Strong guarantee.
3799 
3800       @note All references, pointers, or iterators
3801       referring to contained elements are invalidated. Any
3802       past-the-end iterators are also invalidated.
3803 
3804       @return `*this`
3805 
3806       @param pos The index to replace at.
3807       @param n1 The number of characters to replace.
3808       @param s The string to replace with.
3809       @param n2 The length of the string to replace with.
3810 
3811       @throw std::length_error `size() + (n2 - rcount) > max_size()`
3812       @throw std::out_of_range `pos > size()`
3813   */
3814   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3815   basic_static_string&
replace(size_type pos,size_type n1,const_pointer s,size_type n2)3816   replace(
3817     size_type pos,
3818     size_type n1,
3819     const_pointer s,
3820     size_type n2)
3821   {
3822     return replace(data() + pos, data() + pos + capped_length(pos, n1), s, n2);
3823   }
3824 
3825   /** Replace a part of the string.
3826 
3827       Replaces `rcount` characters starting at index `pos` with those of
3828       `{s, s + len)`, where the length of the string `len` is `traits_type::length(s)` and `rcount`
3829       is `std::min(n1, size() - pos)`.
3830 
3831       @par Exception Safety
3832 
3833       Strong guarantee.
3834 
3835       @note All references, pointers, or iterators
3836       referring to contained elements are invalidated. Any
3837       past-the-end iterators are also invalidated.
3838 
3839       @return `*this`
3840 
3841       @param pos The index to replace at.
3842       @param n1 The number of characters to replace.
3843       @param s The string to replace with.
3844 
3845       @throw std::length_error `size() + (len - rcount) > max_size()`
3846       @throw std::out_of_range `pos > size()`
3847   */
3848   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3849   basic_static_string&
replace(size_type pos,size_type n1,const_pointer s)3850   replace(
3851     size_type pos,
3852     size_type n1,
3853     const_pointer s)
3854   {
3855     return replace(pos, n1, s, traits_type::length(s));
3856   }
3857 
3858   /** Replace a part of the string.
3859 
3860       Replaces `rcount` characters starting at index `pos` with `n2` copies
3861       of `c`, where `rcount` is `std::min(n1, size() - pos)`.
3862 
3863       @par Exception Safety
3864 
3865       Strong guarantee.
3866 
3867       @note All references, pointers, or iterators
3868       referring to contained elements are invalidated. Any
3869       past-the-end iterators are also invalidated.
3870 
3871       @return `*this`
3872 
3873       @param pos The index to replace at.
3874       @param n1 The number of characters to replace.
3875       @param n2 The number of characters to replace with.
3876       @param c The character to replace with.
3877 
3878       @throw std::length_error `size() + (n2 - rcount) > max_size()`
3879       @throw std::out_of_range `pos > size()`
3880   */
3881   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3882   basic_static_string&
replace(size_type pos,size_type n1,size_type n2,value_type c)3883   replace(
3884     size_type pos,
3885     size_type n1,
3886     size_type n2,
3887     value_type c)
3888   {
3889     return replace(data() + pos, data() + pos + capped_length(pos, n1), n2, c);
3890   }
3891 
3892   /** Replace a part of the string.
3893 
3894       Replaces the characters in the range `{i1, i2)`
3895       with those of `str`.
3896 
3897       @par Precondition
3898 
3899       `{i1, i2)` is a valid range.
3900 
3901       @par Exception Safety
3902 
3903       Strong guarantee.
3904 
3905       @note The replacement is done unchecked when
3906       the capacity of `str` differs from that of the
3907       string the function is called on.
3908 
3909       All references, pointers, or iterators
3910       referring to contained elements are invalidated. Any
3911       past-the-end iterators are also invalidated.
3912 
3913       @tparam M The size of the input string.
3914 
3915       @return `*this`
3916 
3917       @param i1 An iterator referring to the first character to replace.
3918       @param i2 An iterator referring past the end of
3919       the last character to replace.
3920       @param str The string to replace with.
3921 
3922       @throw std::length_error `size() + (str.size() - std::distance(i1, i2)) > max_size()`
3923   */
3924   template<std::size_t M>
3925   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3926   basic_static_string&
replace(const_iterator i1,const_iterator i2,const basic_static_string<M,CharT,Traits> & str)3927   replace(
3928     const_iterator i1,
3929     const_iterator i2,
3930     const basic_static_string<M, CharT, Traits>& str)
3931   {
3932     return replace_unchecked(i1, i2, str.data(), str.size());
3933   }
3934 
3935 #ifndef BOOST_STATIC_STRING_DOCS
3936   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3937   basic_static_string&
replace(const_iterator i1,const_iterator i2,const basic_static_string & str)3938   replace(
3939     const_iterator i1,
3940     const_iterator i2,
3941     const basic_static_string& str)
3942   {
3943     return replace(i1, i2, str.data(), str.size());
3944   }
3945 #endif
3946 
3947   /** Replace a part of the string.
3948 
3949       Constructs a temporary `string_view_type` object `sv` from `t`, and
3950       replaces the characters in the range `{i1, i2)` with those
3951       of `sv`.
3952 
3953       @par Precondition
3954 
3955       `{i1, i2)` is a valid range.
3956 
3957       @par Exception Safety
3958 
3959       Strong guarantee.
3960 
3961       @note All references, pointers, or iterators
3962       referring to contained elements are invalidated. Any
3963       past-the-end iterators are also invalidated.
3964 
3965       @tparam T The type of the object to convert.
3966 
3967       @par Constraints
3968 
3969       `std::is_convertible<const T&, string_view>::value &&
3970       !std::is_convertible<const T&, const CharT*>::value`.
3971 
3972       @return `*this`
3973 
3974       @param i1 An iterator referring to the first character to replace.
3975       @param i2 An iterator referring past the end of
3976       the last character to replace.
3977       @param t The object to replace with.
3978 
3979       @throw std::length_error `size() + (sv.size() - std::distance(i1, i2)) > max_size()`
3980   */
3981   template<typename T
3982 #ifndef BOOST_STATIC_STRING_DOCS
3983     , typename = detail::enable_if_viewable_t<T, CharT, Traits>
3984 #endif
3985   >
3986   BOOST_STATIC_STRING_CPP14_CONSTEXPR
3987   basic_static_string&
replace(const_iterator i1,const_iterator i2,const T & t)3988   replace(
3989     const_iterator i1,
3990     const_iterator i2,
3991     const T& t)
3992   {
3993     const string_view_type sv = t;
3994     return replace(i1, i2, sv.begin(), sv.end());
3995   }
3996 
3997   /** Replace a part of the string.
3998 
3999       Replaces the characters in the range `{i1, i2)` with those of
4000       `{s, s + n)`.
4001 
4002       @par Precondition
4003 
4004       `{i1, i2)` is a valid range.
4005 
4006       @par Exception Safety
4007 
4008       Strong guarantee.
4009 
4010       @note All references, pointers, or iterators
4011       referring to contained elements are invalidated. Any
4012       past-the-end iterators are also invalidated.
4013 
4014       @return `*this`
4015 
4016       @param i1 An iterator referring to the first character to replace.
4017       @param i2 An iterator referring past the end of
4018       the last character to replace.
4019       @param s The string to replace with.
4020       @param n The length of the string to replace with.
4021 
4022       @throw std::length_error `size() + (n - std::distance(i1, i2)) > max_size()`
4023   */
4024   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4025   basic_static_string&
replace(const_iterator i1,const_iterator i2,const_pointer s,size_type n)4026   replace(
4027     const_iterator i1,
4028     const_iterator i2,
4029     const_pointer s,
4030     size_type n)
4031   {
4032     return replace(i1, i2, s, s + n);
4033   }
4034 
4035   /** Replace a part of the string.
4036 
4037       Replaces the characters in the range `{i1, i2)` with those of
4038       `{s, s + len)`, where the length of the string `len` is `traits_type::length(s)`.
4039 
4040       @par Precondition
4041 
4042       `{i1, i2)` shall be a valid range.
4043 
4044       @par Exception Safety
4045 
4046       Strong guarantee.
4047 
4048       @note All references, pointers, or iterators
4049       referring to contained elements are invalidated. Any
4050       past-the-end iterators are also invalidated.
4051 
4052       @return `*this`
4053 
4054       @param i1 An iterator referring to the first character to replace.
4055       @param i2 An iterator referring past the end of
4056       the last character to replace.
4057       @param s The string to replace with.
4058 
4059       @throw std::length_error `size() + (len - std::distance(i1, i2)) > max_size()`
4060   */
4061   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4062   basic_static_string&
replace(const_iterator i1,const_iterator i2,const_pointer s)4063   replace(
4064     const_iterator i1,
4065     const_iterator i2,
4066     const_pointer s)
4067   {
4068     return replace(i1, i2, s, traits_type::length(s));
4069   }
4070 
4071   /** Replace a part of the string.
4072 
4073       Replaces the characters in the range `{i1, i2)` with
4074       `n` copies of `c`.
4075 
4076       @par Precondition
4077 
4078       `{i1, i2)` is a valid range.
4079 
4080       @par Exception Safety
4081 
4082       Strong guarantee.
4083 
4084       @note All references, pointers, or iterators
4085       referring to contained elements are invalidated. Any
4086       past-the-end iterators are also invalidated.
4087 
4088       @return `*this`
4089 
4090       @param i1 An iterator referring to the first character to replace.
4091       @param i2 An iterator past the end of
4092       the last character to replace.
4093       @param n The number of characters to replace with.
4094       @param c The character to replace with.
4095 
4096       @throw std::length_error `size() + (n - std::distance(i1, i2)) > max_size()`
4097   */
4098   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4099   basic_static_string&
4100   replace(
4101     const_iterator i1,
4102     const_iterator i2,
4103     size_type n,
4104     value_type c);
4105 
4106   /** Replace a part of the string.
4107 
4108       Replaces the characters in the range `{i1, i2)`
4109       with those of `{j1, j2)`.
4110 
4111       @par Precondition
4112 
4113       `{i1, i2)` is a valid range.
4114 
4115       `{j1, j2)` is a valid range.
4116 
4117       @par Exception Safety
4118 
4119       Strong guarantee.
4120 
4121       @note All references, pointers, or iterators
4122       referring to contained elements are invalidated. Any
4123       past-the-end iterators are also invalidated.
4124 
4125       @tparam InputIterator The type of the iterators.
4126 
4127       @par Constraints
4128 
4129       `InputIterator` satisfies __InputIterator__ and does not
4130       satisfy __ForwardIterator__.
4131 
4132       @return `*this`
4133 
4134       @param i1 An iterator referring to the first character to replace.
4135       @param i2 An iterator referring past the end of
4136       the last character to replace.
4137       @param j1 An iterator referring to the first character to replace with.
4138       @param j2 An iterator referring past the end of
4139       the last character to replace with.
4140 
4141       @throw std::length_error `size() + (inserted - std::distance(i1, i2)) > max_size()`
4142   */
4143   template<typename InputIterator>
4144   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4145 #ifdef BOOST_STATIC_STRING_DOCS
4146   basic_static_string&
4147 #else
4148   typename std::enable_if<
4149     detail::is_input_iterator<
4150       InputIterator>::value &&
4151         !detail::is_forward_iterator<
4152           InputIterator>::value,
4153             basic_static_string<N, CharT, Traits>&>::type
4154 #endif
4155   replace(
4156     const_iterator i1,
4157     const_iterator i2,
4158     InputIterator j1,
4159     InputIterator j2);
4160 
4161 #ifndef BOOST_STATIC_STRING_DOCS
4162   template<typename ForwardIterator>
4163   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4164   typename std::enable_if<
4165     detail::is_forward_iterator<
4166       ForwardIterator>::value,
4167         basic_static_string<N, CharT, Traits>&>::type
4168   replace(
4169     const_iterator i1,
4170     const_iterator i2,
4171     ForwardIterator j1,
4172     ForwardIterator j2);
4173 #endif
4174 
4175   /** Replace a part of the string.
4176 
4177       Replaces the characters in the range `{i1, i2)`
4178       with those of contained in the initializer list `il`.
4179 
4180       @par Precondition
4181 
4182       `{i1, i2)` is a valid range.
4183 
4184       @par Exception Safety
4185 
4186       Strong guarantee.
4187 
4188       @note All references, pointers, or iterators
4189       referring to contained elements are invalidated. Any
4190       past-the-end iterators are also invalidated.
4191 
4192       @return `*this`
4193 
4194       @param i1 An iterator referring to the first character to replace.
4195       @param i2 An iterator past the end of
4196       the last character to replace.
4197       @param il The initializer list to replace with.
4198 
4199       @throw std::length_error `size() + (il.size() - std::distance(i1, i2)) > max_size()`
4200   */
4201   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4202   basic_static_string&
replace(const_iterator i1,const_iterator i2,std::initializer_list<value_type> il)4203   replace(
4204     const_iterator i1,
4205     const_iterator i2,
4206     std::initializer_list<value_type> il)
4207   {
4208     return replace_unchecked(i1, i2, il.begin(), il.size());
4209   }
4210 
4211   //--------------------------------------------------------------------------
4212   //
4213   // Search
4214   //
4215   //--------------------------------------------------------------------------
4216 
4217   /** Find the first occurrence of a string within the string.
4218 
4219       Constructs a temporary `string_view_type` object `sv` from `t`, and finds
4220       the first occurrence of `sv` within the string starting at the index `pos`.
4221 
4222       @par Complexity
4223 
4224       Linear.
4225 
4226       @note An empty string is always found.
4227 
4228       @tparam T The type of the object to convert.
4229 
4230       @par Constraints
4231 
4232       `std::is_convertible<const T&, string_view>::value &&
4233       !std::is_convertible<const T&, const CharT*>::value`.
4234 
4235       @return The lowest index `idx` greater than or equal to `pos`
4236       where each element of `{sv.begin(), sv.end())` is equal to
4237       that of `{begin() + idx, begin() + idx + count)` if one exists,
4238       and @ref npos otherwise.
4239 
4240       @param t The string to search for.
4241       @param pos The index to start searching at. The default argument
4242       for this parameter is `0`.
4243   */
4244   template<typename T
4245 #ifndef BOOST_STATIC_STRING_DOCS
4246     , typename = detail::enable_if_viewable_t<T, CharT, Traits>
4247 #endif
4248   >
4249   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4250   size_type
find(const T & t,size_type pos=0) const4251   find(
4252     const T& t,
4253     size_type pos = 0) const
4254       noexcept(detail::is_nothrow_convertible<const T&, string_view_type>::value)
4255   {
4256     const string_view_type sv = t;
4257     return find(sv.data(), pos, sv.size());
4258   }
4259 
4260     /** Find the first occurrence of a string within the string.
4261 
4262       Finds the first occurrence of `str` within the
4263       string starting at the index `pos`.
4264 
4265       @par Complexity
4266 
4267       Linear.
4268 
4269       @return The lowest index `idx` greater than or equal to `pos`
4270       where each element of `str` is equal to that of
4271       `{begin() + idx, begin() + idx + str.size())`
4272       if one exists, and @ref npos otherwise.
4273 
4274       @param str The string to search for.
4275       @param pos The index to start searching at. The default argument for
4276       this parameter is `0`.
4277   */
4278   template<std::size_t M>
4279   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4280   size_type
find(const basic_static_string<M,CharT,Traits> & str,size_type pos=0) const4281   find(
4282     const basic_static_string<M, CharT, Traits>& str,
4283     size_type pos = 0) const noexcept
4284   {
4285     return find(str.data(), pos, str.size());
4286   }
4287 
4288   /** Find the first occurrence of a string within the string.
4289 
4290       Finds the first occurrence of the string pointed to
4291       by `s` within the string starting at the index `pos`.
4292 
4293       @par Complexity
4294 
4295       Linear.
4296 
4297       @note An empty string is always found.
4298 
4299       @return The lowest index `idx` greater than or equal to `pos`
4300       where each element of `{s, s + n)` is equal to that of
4301       `{begin() + idx, begin() + idx + n)` if one exists,
4302       and @ref npos otherwise.
4303 
4304       @param s The string to search for.
4305       @param pos The index to start searching at.
4306       @param n The length of the string to search for.
4307   */
4308   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4309   size_type
4310   find(
4311     const_pointer s,
4312     size_type pos,
4313     size_type n) const noexcept;
4314 
4315   /** Find the first occurrence of a string within the string.
4316 
4317       Finds the first occurrence of the string pointed to by `s`
4318       of length `count` within the string starting at the index `pos`,
4319       where `count` is `traits_type::length(s)`.
4320 
4321       @par Complexity
4322 
4323       Linear.
4324 
4325       @note An empty string is always found.
4326 
4327       @return The lowest index `idx` greater than or equal to `pos`
4328       where each element of `{s, s + count)` is equal to that of
4329       `{begin() + idx, begin() + idx + count)` if one exists,
4330       and @ref npos otherwise.
4331 
4332       @param s The string to search for.
4333       @param pos The index to start searching at. The default argument
4334       for this parameter is `0`.
4335   */
4336   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4337   size_type
find(const_pointer s,size_type pos=0) const4338   find(
4339     const_pointer s,
4340     size_type pos = 0) const noexcept
4341   {
4342     return find(s, pos, traits_type::length(s));
4343   }
4344 
4345   /** Find the first occurrence of a character within the string.
4346 
4347       Finds the first occurrence of `c` within the string
4348       starting at the index `pos`.
4349 
4350       @par Complexity
4351 
4352       Linear.
4353 
4354       @return The index corrosponding to the first occurrence of `c` within
4355       `{begin() + pos, end())` if it exists, and @ref npos otherwise.
4356 
4357       @param c The character to search for.
4358       @param pos The index to start searching at. The default argument
4359       for this parameter is `0`.
4360   */
4361   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4362   size_type
find(value_type c,size_type pos=0) const4363   find(
4364     value_type c,
4365     size_type pos = 0) const noexcept
4366   {
4367     return find(&c, pos, 1);
4368   }
4369 
4370 
4371   /** Find the last occurrence of a string within the string.
4372 
4373       Constructs a temporary `string_view_type` object `sv` from `t`, and finds
4374       the last occurrence of `sv` within the string starting before or at
4375       the index `pos`.
4376 
4377       @par Complexity
4378 
4379       Linear.
4380 
4381       @tparam T The type of the object to convert.
4382 
4383       @par Constraints
4384 
4385       `std::is_convertible<const T&, string_view>::value &&
4386       !std::is_convertible<const T&, const CharT*>::value`.
4387 
4388       @return The highest index `idx` less than or equal to `pos`
4389       where each element of `{sv.begin(), sv.end())` is equal to
4390       that of `{begin() + idx, begin() + idx + count)` if one exists,
4391       and @ref npos otherwise.
4392 
4393       @param t The string to search for.
4394       @param pos The index to start searching at. The default argument
4395       for this parameter is @ref npos.
4396   */
4397   template<typename T
4398 #ifndef BOOST_STATIC_STRING_DOCS
4399     , typename = detail::enable_if_viewable_t<T, CharT, Traits>
4400 #endif
4401   >
4402   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4403   size_type
rfind(const T & t,size_type pos=npos) const4404   rfind(
4405     const T& t,
4406     size_type pos = npos) const
4407       noexcept(detail::is_nothrow_convertible<const T&, string_view_type>::value)
4408   {
4409     const string_view_type sv = t;
4410     return rfind(sv.data(), pos, sv.size());
4411   }
4412 
4413   /** Find the last occurrence of a string within the string.
4414 
4415       Finds the last occurrence of `str` within the string
4416       starting before or at the index `pos`.
4417 
4418       @par Complexity
4419 
4420       Linear.
4421 
4422       @return The highest index `idx` less than or equal to `pos`
4423       where each element of `str` is equal to that
4424       of `{begin() + idx, begin() + idx + str.size())`
4425       if one exists, and @ref npos otherwise.
4426 
4427       @param str The string to search for.
4428       @param pos The index to start searching at. The default argument for
4429       this parameter is @ref npos.
4430   */
4431   template<std::size_t M>
4432   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4433   size_type
rfind(const basic_static_string<M,CharT,Traits> & str,size_type pos=npos) const4434   rfind(
4435     const basic_static_string<M, CharT, Traits>& str,
4436     size_type pos = npos) const noexcept
4437   {
4438     return rfind(str.data(), pos, str.size());
4439   }
4440 
4441   /** Find the last occurrence of a string within the string.
4442 
4443       Finds the last occurrence of the string pointed to
4444       by `s` within the string starting before or at
4445       the index `pos`.
4446 
4447       @par Complexity
4448 
4449       Linear.
4450 
4451       @return The highest index `idx` less than or equal to `pos`
4452       where each element of `{s, s + n)` is equal to that of
4453       `{begin() + idx, begin() + idx + n)` if one exists,
4454       and @ref npos otherwise.
4455 
4456       @param s The string to search for.
4457       @param pos The index to start searching at.
4458       @param n The length of the string to search for.
4459   */
4460   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4461   size_type
4462   rfind(
4463     const_pointer s,
4464     size_type pos,
4465     size_type n) const noexcept;
4466 
4467   /** Find the last occurrence of a string within the string.
4468 
4469       Finds the last occurrence of the string pointed to by `s`
4470       of length `count` within the string starting before or at the
4471       index `pos`, where `count` is `traits_type::length(s)`.
4472 
4473       @par Complexity
4474 
4475       Linear.
4476 
4477       @return The highest index `idx` less than or equal to `pos`
4478       where each element of `{s, s + count)` is equal to that of
4479       `{begin() + idx, begin() + idx + count)` if one exists,
4480       and @ref npos otherwise.
4481 
4482       @param s The string to search for.
4483       @param pos The index to stop searching at. The default argument
4484       for this parameter is @ref npos.
4485   */
4486   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4487   size_type
rfind(const_pointer s,size_type pos=npos) const4488   rfind(
4489     const_pointer s,
4490     size_type pos = npos) const noexcept
4491   {
4492     return rfind(s, pos, traits_type::length(s));
4493   }
4494 
4495   /** Find the last occurrence of a character within the string.
4496 
4497       Finds the last occurrence of `c` within the string
4498       starting before or at the index `pos`.
4499 
4500       @par Complexity
4501 
4502       Linear.
4503 
4504       @return The index corrosponding to the last occurrence of `c` within
4505       `{begin(), begin() + pos}` if it exists, and @ref npos otherwise.
4506 
4507       @param c The character to search for.
4508       @param pos The index to stop searching at. The default argument
4509       for this parameter is @ref npos.
4510   */
4511   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4512   size_type
rfind(value_type c,size_type pos=npos) const4513   rfind(
4514     value_type c,
4515     size_type pos = npos) const noexcept
4516   {
4517     return rfind(&c, pos, 1);
4518   }
4519 
4520   /** Find the first occurrence of any of the characters within the string.
4521 
4522       Constructs a temporary `string_view_type` object `sv` from `t`, and finds
4523       the first occurrence of any of the characters in `sv`
4524       within the string starting at the index `pos`.
4525 
4526       @par Complexity
4527 
4528       Linear.
4529 
4530       @tparam T The type of the object to convert.
4531 
4532       @par Constraints
4533 
4534       `std::is_convertible<const T&, string_view>::value &&
4535       !std::is_convertible<const T&, const CharT*>::value`.
4536 
4537       @return The index corrosponding to the first occurrence of
4538       any of the characters in `{sv.begin(), sv.end())` within
4539       `{begin() + pos, end())` if it exists, and @ref npos otherwise.
4540 
4541       @param t The characters to search for.
4542       @param pos The index to start searching at. The default argument
4543       for this parameter is `0`.
4544   */
4545   template<typename T
4546 #ifndef BOOST_STATIC_STRING_DOCS
4547     , typename = detail::enable_if_viewable_t<T, CharT, Traits>
4548 #endif
4549   >
4550   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4551   size_type
find_first_of(const T & t,size_type pos=0) const4552   find_first_of(
4553     const T& t,
4554     size_type pos = 0) const
4555       noexcept(detail::is_nothrow_convertible<const T&, string_view_type>::value)
4556   {
4557     const string_view_type sv = t;
4558     return find_first_of(sv.data(), pos, sv.size());
4559   }
4560 
4561   /** Find the first occurrence of any of the characters within the string.
4562 
4563       Finds the first occurrence of any of the characters within `str` within the
4564       string starting at the index `pos`.
4565 
4566       @par Complexity
4567 
4568       Linear.
4569 
4570       @return The index corrosponding to the first occurrence of any of the characters
4571       of `str` within `{begin() + pos, end())` if it exists, and @ref npos otherwise.
4572 
4573       @param str The characters to search for.
4574       @param pos The index to start searching at. The default argument for
4575       this parameter is `0`.
4576   */
4577   template<std::size_t M>
4578   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4579   size_type
find_first_of(const basic_static_string<M,CharT,Traits> & str,size_type pos=0) const4580   find_first_of(
4581     const basic_static_string<M, CharT, Traits>& str,
4582     size_type pos = 0) const noexcept
4583   {
4584     return find_first_of(str.data(), pos, str.size());
4585   }
4586 
4587   /** Find the first occurrence of any of the characters within the string.
4588 
4589       Finds the first occurrence of any of the characters within the string pointed to
4590       by `s` within the string starting at the index `pos`.
4591 
4592       @par Complexity
4593 
4594       Linear.
4595 
4596       @return The index corrosponding to the first occurrence
4597       of any of the characters in `{s, s + n)` within `{begin() + pos, end())`
4598       if it exists, and @ref npos otherwise.
4599 
4600       @param s The characters to search for.
4601       @param pos The index to start searching at.
4602       @param n The length of the string to search for.
4603   */
4604   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4605   size_type
4606   find_first_of(
4607     const_pointer s,
4608     size_type pos,
4609     size_type n) const noexcept;
4610 
4611   /** Find the first occurrence of any of the characters within the string.
4612 
4613       Finds the first occurrence of the any of the characters within string
4614       pointed to by `s` of length `count` within the string starting at the
4615       index `pos`, where `count` is `traits_type::length(s)`.
4616 
4617       @par Complexity
4618 
4619       Linear.
4620 
4621       @return The index corrosponding to the first occurrence of any of
4622       the characters in `{s, s + count)` within
4623       `{begin() + pos, end())` if it exists, and @ref npos otherwise.
4624 
4625       @param s The characters to search for.
4626       @param pos The index to start searching at. The default argument
4627       for this parameter is `0`.
4628   */
4629   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4630   size_type
find_first_of(const_pointer s,size_type pos=0) const4631   find_first_of(
4632     const_pointer s,
4633     size_type pos = 0) const noexcept
4634   {
4635     return find_first_of(s, pos, traits_type::length(s));
4636   }
4637 
4638   /** Find the first occurrence of a character within the string.
4639 
4640       Finds the first occurrence of `c` within the string
4641       starting at the index `pos`.
4642 
4643       @par Complexity
4644 
4645       Linear.
4646 
4647       @return The index corrosponding to the first occurrence of `c` within
4648       `{begin() + pos, end())` if it exists, and @ref npos otherwise.
4649 
4650       @param c The character to search for.
4651       @param pos The index to start searching at. The default argument
4652       for this parameter is `0`.
4653   */
4654   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4655   size_type
find_first_of(value_type c,size_type pos=0) const4656   find_first_of(
4657     value_type c,
4658     size_type pos = 0) const noexcept
4659   {
4660     return find_first_of(&c, pos, 1);
4661   }
4662 
4663   /** Find the last occurrence of any of the characters within the string.
4664 
4665       Constructs a temporary `string_view_type` object `sv` from `t`, and finds
4666       the last occurrence of any of the characters in `sv`
4667       within the string before or at the index `pos`.
4668 
4669       @par Complexity
4670 
4671       Linear.
4672 
4673       @tparam T The type of the object to convert.
4674 
4675       @par Constraints
4676 
4677       `std::is_convertible<const T&, string_view>::value &&
4678       !std::is_convertible<const T&, const CharT*>::value`.
4679 
4680       @return The index corrosponding to the last occurrence of
4681       any of the characters in `{sv.begin(), sv.end())` within
4682       `{begin(), begin() + pos}` if it exists, and @ref npos otherwise.
4683 
4684       @param t The characters to search for.
4685       @param pos The index to stop searching at. The default argument
4686       for this parameter is @ref npos.
4687   */
4688   template<typename T
4689 #ifndef BOOST_STATIC_STRING_DOCS
4690     , typename = detail::enable_if_viewable_t<T, CharT, Traits>
4691 #endif
4692   >
4693   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4694   size_type
find_last_of(const T & t,size_type pos=npos) const4695   find_last_of(
4696     const T& t,
4697     size_type pos = npos) const
4698       noexcept(detail::is_nothrow_convertible<const T&, string_view_type>::value)
4699   {
4700     const string_view_type sv = t;
4701     return find_last_of(sv.data(), pos, sv.size());
4702   }
4703 
4704   /** Find the last occurrence of any of the characters within the string.
4705 
4706       Finds the last occurrence of any of the characters within `str` within the
4707       string starting before or at the index `pos`.
4708 
4709       @par Complexity
4710 
4711       Linear.
4712 
4713       @return The index corrosponding to the last occurrence of any of the characters
4714       of `str` within `{begin(), begin() + pos}` if it exists, and @ref npos otherwise.
4715 
4716       @param str The characters to search for.
4717       @param pos The index to stop searching at. The default argument for
4718       this parameter is @ref npos.
4719   */
4720   template<std::size_t M>
4721   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4722   size_type
find_last_of(const basic_static_string<M,CharT,Traits> & str,size_type pos=npos) const4723   find_last_of(
4724     const basic_static_string<M, CharT, Traits>& str,
4725     size_type pos = npos) const noexcept
4726   {
4727     return find_last_of(str.data(), pos, str.size());
4728   }
4729 
4730   /** Find the last occurrence of any of the characters within the string.
4731 
4732       Finds the last occurrence of any of the characters within the string pointed to
4733       by `s` within the string before or at the index `pos`.
4734 
4735       @par Complexity
4736 
4737       Linear.
4738 
4739       @return The index corrosponding to the last occurrence
4740       of any of the characters in `{s, s + n)` within `{begin(), begin() + pos}`
4741       if it exists, and @ref npos otherwise.
4742 
4743       @param s The characters to search for.
4744       @param pos The index to stop searching at.
4745       @param n The length of the string to search for.
4746   */
4747   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4748   size_type
4749   find_last_of(
4750     const_pointer s,
4751     size_type pos,
4752     size_type n) const noexcept;
4753 
4754   /** Find the last occurrence of any of the characters within the string.
4755 
4756       Finds the last occurrence of any of the characters within the string pointed to
4757       by `s` of length `count` within the string before or at the index `pos`,
4758       where `count` is `traits_type::length(s)`.
4759 
4760       @par Complexity
4761 
4762       Linear.
4763 
4764       @return The index corrosponding to the last occurrence
4765       of any of the characters in `{s, s + count)` within `{begin(), begin() + pos}`
4766       if it exists, and @ref npos otherwise.
4767 
4768       @param s The characters to search for.
4769       @param pos The index to stop searching at. The default argument for
4770       this parameter is @ref npos.
4771   */
4772   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4773   size_type
find_last_of(const_pointer s,size_type pos=npos) const4774   find_last_of(
4775     const_pointer s,
4776     size_type pos = npos) const noexcept
4777   {
4778     return find_last_of(s, pos, traits_type::length(s));
4779   }
4780 
4781   /** Find the last occurrence of a character within the string.
4782 
4783       Finds the last occurrence of `c` within the string
4784       before or at the index `pos`.
4785 
4786       @par Complexity
4787 
4788       Linear.
4789 
4790       @return The index corrosponding to the last occurrence of `c` within
4791       `{begin(), begin() + pos}` if it exists, and @ref npos otherwise.
4792 
4793       @param c The character to search for.
4794       @param pos The index to stop searching at. The default argument
4795       for this parameter is @ref npos.
4796   */
4797   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4798   size_type
find_last_of(value_type c,size_type pos=npos) const4799   find_last_of(
4800     value_type c,
4801     size_type pos = npos) const noexcept
4802   {
4803     return find_last_of(&c, pos, 1);
4804   }
4805 
4806   /** Find the first occurrence of a character not within the string.
4807 
4808       Constructs a temporary `string_view_type` object `sv` from `t`, and finds
4809       the first character that is not within `sv`, starting at the index `pos`.
4810 
4811       @par Complexity
4812 
4813       Linear.
4814 
4815       @tparam T The type of the object to convert.
4816 
4817       @par Constraints
4818 
4819       `std::is_convertible<const T&, string_view>::value &&
4820       !std::is_convertible<const T&, const CharT*>::value`.
4821 
4822       @return The index corrosponding to the first occurrence of
4823       a character that is not in `{sv.begin(), sv.end())` within
4824       `{begin() + pos, end())` if it exists, and @ref npos otherwise.
4825 
4826       @param t The characters to ignore.
4827       @param pos The index to start searching at. The default argument
4828       for this parameter is `0`.
4829   */
4830   template<typename T
4831 #ifndef BOOST_STATIC_STRING_DOCS
4832     , typename = detail::enable_if_viewable_t<T, CharT, Traits>
4833 #endif
4834   >
4835   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4836   size_type
find_first_not_of(const T & t,size_type pos=0) const4837   find_first_not_of(
4838     const T& t,
4839     size_type pos = 0) const
4840       noexcept(detail::is_nothrow_convertible<const T&, string_view_type>::value)
4841   {
4842     const string_view_type sv = t;
4843     return find_first_not_of(sv.data(), pos, sv.size());
4844   }
4845 
4846   /** Find the first occurrence of any of the characters not within the string.
4847 
4848       Finds the first occurrence of a character that is not within `str`
4849       within the string starting at the index `pos`.
4850 
4851       @par Complexity
4852 
4853       Linear.
4854 
4855       @return The index corrosponding to the first character of `{begin() + pos, end())`
4856       that is not within `str` if it exists, and @ref npos otherwise.
4857 
4858       @param str The characters to ignore.
4859       @param pos The index to start searching at. The default argument for
4860       this parameter is `0`.
4861   */
4862   template<std::size_t M>
4863   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4864   size_type
find_first_not_of(const basic_static_string<M,CharT,Traits> & str,size_type pos=0) const4865   find_first_not_of(
4866     const basic_static_string<M, CharT, Traits>& str,
4867     size_type pos = 0) const noexcept
4868   {
4869     return find_first_not_of(str.data(), pos, str.size());
4870   }
4871 
4872   /** Find the first occurrence of any of the characters not within the string.
4873 
4874       Finds the first occurrence of a character that is not within the string
4875       pointed to by `s` within the string starting at the index `pos`.
4876 
4877       @par Complexity
4878 
4879       Linear.
4880 
4881       @return The index corrosponding to the first character of `{begin() + pos, end())`
4882       that is not within `{s, s + n)` if it exists, and @ref npos otherwise.
4883 
4884       @param s The characters to ignore.
4885       @param pos The index to start searching at. The default argument for
4886       this parameter is `0`.
4887       @param n The length of the characters to ignore.
4888   */
4889   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4890   size_type
4891   find_first_not_of(
4892     const_pointer s,
4893     size_type pos,
4894     size_type n) const noexcept;
4895 
4896   /** Find the first occurrence of any of the characters not within the string.
4897 
4898       Finds the first occurrence of a character that is not within the string
4899       pointed to by `s` of length `count` within the string starting
4900       at the index `pos`, where `count` is `traits_type::length(s)`.
4901 
4902       @par Complexity
4903 
4904       Linear.
4905 
4906       @return The index corrosponding to the first character of `{begin() + pos, end())`
4907       that is not within `{s, s + count)` if it exists, and @ref npos otherwise.
4908 
4909       @param s The characters to ignore.
4910       @param pos The index to start searching at. The default argument for
4911       this parameter is `0`.
4912   */
4913   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4914   size_type
find_first_not_of(const_pointer s,size_type pos=0) const4915   find_first_not_of(
4916     const_pointer s,
4917     size_type pos = 0) const noexcept
4918   {
4919     return find_first_not_of(s, pos, traits_type::length(s));
4920   }
4921 
4922   /** Find the first occurrence of a character not equal to `c`.
4923 
4924       Finds the first occurrence of a character that is not equal
4925       to `c`.
4926 
4927       @par Complexity
4928 
4929       Linear.
4930 
4931       @return The index corrosponding to the first character of `{begin() + pos, end())`
4932       that is not equal to `c` if it exists, and @ref npos otherwise.
4933 
4934       @param c The character to ignore.
4935       @param pos The index to start searching at. The default argument for
4936       this parameter is `0`.
4937   */
4938   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4939   size_type
find_first_not_of(value_type c,size_type pos=0) const4940   find_first_not_of(
4941     value_type c,
4942     size_type pos = 0) const noexcept
4943   {
4944     return find_first_not_of(&c, pos, 1);
4945   }
4946 
4947   /** Find the last occurrence of a character not within the string.
4948 
4949       Constructs a temporary `string_view_type` object `sv` from `t`, and finds
4950       the last character that is not within `sv`, starting at the index `pos`.
4951 
4952       @par Complexity
4953 
4954       Linear.
4955 
4956       @tparam T The type of the object to convert.
4957 
4958       @par Constraints
4959 
4960       `std::is_convertible<const T&, string_view>::value &&
4961       !std::is_convertible<const T&, const CharT*>::value`.
4962 
4963       @return The index corrosponding to the last occurrence of
4964       a character that is not in `{sv.begin(), sv.end())` within
4965       `{begin(), begin() + pos}` if it exists, and @ref npos otherwise.
4966 
4967       @param t The characters to ignore.
4968       @param pos The index to start searching at. The default argument
4969       for this parameter is @ref npos.
4970   */
4971   template<typename T
4972 #ifndef BOOST_STATIC_STRING_DOCS
4973     , typename = detail::enable_if_viewable_t<T, CharT, Traits>
4974 #endif
4975   >
4976   BOOST_STATIC_STRING_CPP14_CONSTEXPR
4977   size_type
find_last_not_of(const T & t,size_type pos=npos) const4978   find_last_not_of(
4979     const T& t,
4980     size_type pos = npos) const
4981       noexcept(detail::is_nothrow_convertible<const T&, string_view_type>::value)
4982   {
4983     const string_view_type sv = t;
4984     return find_last_not_of(sv.data(), pos, sv.size());
4985   }
4986 
4987   /** Find the last occurrence of a character not within the string.
4988 
4989       Finds the last occurrence of a character that is not within `str`
4990       within the string before or at the index `pos`.
4991 
4992       @par Complexity
4993 
4994       Linear.
4995 
4996       @return The index corrosponding to the last character of `{begin(), begin() + pos}`
4997       that is not within `str` if it exists, and @ref npos otherwise.
4998 
4999       @param str The characters to ignore.
5000       @param pos The index to stop searching at. The default argument for
5001       this parameter is @ref npos.
5002   */
5003   template<size_t M>
5004   BOOST_STATIC_STRING_CPP14_CONSTEXPR
5005   size_type
find_last_not_of(const basic_static_string<M,CharT,Traits> & str,size_type pos=npos) const5006   find_last_not_of(
5007     const basic_static_string<M, CharT, Traits>& str,
5008     size_type pos = npos) const noexcept
5009   {
5010     return find_last_not_of(str.data(), pos, str.size());
5011   }
5012 
5013   /** Find the last occurrence of a character not within the string.
5014 
5015       Finds the last occurrence of a character that is not within the
5016       string pointed to by `s` within the string before or at the index `pos`.
5017 
5018       @par Complexity
5019 
5020       Linear.
5021 
5022       @return The index corrosponding to the last character of `{begin(), begin() + pos}`
5023       that is not within `{s, s + n)` if it exists, and @ref npos otherwise.
5024 
5025       @param s The characters to ignore.
5026       @param pos The index to stop searching at. The default argument for
5027       this parameter is @ref npos.
5028       @param n The length of the characters to ignore.
5029   */
5030   BOOST_STATIC_STRING_CPP14_CONSTEXPR
5031   size_type
5032   find_last_not_of(
5033     const_pointer s,
5034     size_type pos,
5035     size_type n) const noexcept;
5036 
5037 
5038   /** Find the last occurrence of a character not within the string.
5039 
5040       Finds the last occurrence of a character that is not within the
5041       string pointed to by `s` of length `count` within the string
5042       before or at the index `pos`, where `count` is `traits_type::length(s)`.
5043 
5044       @par Complexity
5045 
5046       Linear.
5047 
5048       @return The index corrosponding to the last character of `{begin(), begin() + pos}`
5049       that is not within `{s, s + count)` if it exists, and @ref npos otherwise.
5050 
5051       @param s The characters to ignore.
5052       @param pos The index to stop searching at. The default argument for
5053       this parameter is @ref npos.
5054   */
5055   BOOST_STATIC_STRING_CPP14_CONSTEXPR
5056   size_type
find_last_not_of(const_pointer s,size_type pos=npos) const5057   find_last_not_of(
5058     const_pointer s,
5059     size_type pos = npos) const noexcept
5060   {
5061     return find_last_not_of(s, pos, traits_type::length(s));
5062   }
5063 
5064   /** Find the last occurrence of a character not equal to `c`.
5065 
5066       Finds the last occurrence of a character that is not equal
5067       to `c` before or at the index `pos`.
5068 
5069       @par Complexity
5070 
5071       Linear.
5072 
5073       @return The index corrosponding to the last character of `{begin(), begin() + pos}`
5074       that is not equal to `c` if it exists, and @ref npos otherwise.
5075 
5076       @param c The character to ignore.
5077       @param pos The index to start searching at. The default argument for
5078       this parameter is @ref npos.
5079   */
5080   BOOST_STATIC_STRING_CPP14_CONSTEXPR
5081   size_type
find_last_not_of(value_type c,size_type pos=npos) const5082   find_last_not_of(
5083     value_type c,
5084     size_type pos = npos) const noexcept
5085   {
5086     return find_last_not_of(&c, pos, 1);
5087   }
5088 
5089   /** Return whether the string begins with a string.
5090 
5091       Returns `true` if the string begins with `s`, and `false` otherwise.
5092 
5093       @par Complexity
5094 
5095       Linear.
5096 
5097       @param s The string view to check for.
5098   */
5099   BOOST_STATIC_STRING_CPP14_CONSTEXPR
5100   bool
starts_with(string_view_type s) const5101   starts_with(
5102     string_view_type s) const noexcept
5103   {
5104     const size_type len = s.size();
5105     return size() >= len && !traits_type::compare(data(), s.data(), len);
5106   }
5107 
5108   /** Return whether the string begins with a character.
5109 
5110       Returns `true` if the string begins with `c`, and `false` otherwise.
5111 
5112       @par Complexity
5113 
5114       Constant.
5115 
5116       @param c The character to check for.
5117   */
5118   BOOST_STATIC_STRING_CPP14_CONSTEXPR
5119   bool
starts_with(value_type c) const5120   starts_with(
5121     value_type c) const noexcept
5122   {
5123     return !empty() && traits_type::eq(front(), c);
5124   }
5125 
5126   /** Return whether the string begins with a string.
5127 
5128       Returns `true` if the string begins with the string
5129       pointed to be `s` of length `traits_type::length(s)`,
5130       and `false` otherwise.
5131 
5132       @par Complexity
5133 
5134       Linear.
5135 
5136       @param s The string to check for.
5137   */
5138   BOOST_STATIC_STRING_CPP14_CONSTEXPR
5139   bool
starts_with(const_pointer s) const5140   starts_with(
5141     const_pointer s) const noexcept
5142   {
5143     const size_type len = traits_type::length(s);
5144     return size() >= len && !traits_type::compare(data(), s, len);
5145   }
5146 
5147   /** Return whether the string ends with a string.
5148 
5149       Returns `true` if the string ends with `s`, and `false` otherwise.
5150 
5151       @par Complexity
5152 
5153       Linear.
5154 
5155       @param s The string view to check for.
5156   */
5157   BOOST_STATIC_STRING_CPP14_CONSTEXPR
5158   bool
ends_with(string_view_type s) const5159   ends_with(
5160     string_view_type s) const noexcept
5161   {
5162     const size_type len = s.size();
5163     return size() >= len && !traits_type::compare(data() + (size() - len), s.data(), len);
5164   }
5165 
5166   /** Return whether the string ends with a character.
5167 
5168       Returns `true` if the string ends with `c`, and `false` otherwise.
5169 
5170       @par Complexity
5171 
5172       Constant.
5173 
5174       @param c The character to check for.
5175   */
5176   BOOST_STATIC_STRING_CPP14_CONSTEXPR
5177   bool
ends_with(value_type c) const5178   ends_with(
5179     value_type c) const noexcept
5180   {
5181     return !empty() && traits_type::eq(back(), c);
5182   }
5183 
5184   /** Return whether the string ends with a string.
5185 
5186       Returns `true` if the string ends with the string
5187       pointed to be `s` of length `traits_type::length(s)`,
5188       and `false` otherwise.
5189 
5190       @par Complexity
5191 
5192       Linear.
5193 
5194       @param s The string to check for.
5195   */
5196   BOOST_STATIC_STRING_CPP14_CONSTEXPR
5197   bool
ends_with(const_pointer s) const5198   ends_with(
5199     const_pointer s) const noexcept
5200   {
5201     const size_type len = traits_type::length(s);
5202     return size() >= len && !traits_type::compare(data() + (size() - len), s, len);
5203   }
5204 
5205 private:
5206   BOOST_STATIC_STRING_CPP14_CONSTEXPR
5207   basic_static_string&
term()5208   term() noexcept
5209   {
5210     this->term_impl();
5211     return *this;
5212   }
5213 
5214   BOOST_STATIC_STRING_CPP14_CONSTEXPR
5215   basic_static_string&
assign_char(value_type ch,std::true_type)5216   assign_char(value_type ch, std::true_type) noexcept
5217   {
5218     this->set_size(1);
5219     traits_type::assign(data()[0], ch);
5220     return term();
5221   }
5222 
5223   BOOST_STATIC_STRING_NORETURN
5224   basic_static_string&
assign_char(value_type,std::false_type)5225   assign_char(value_type, std::false_type)
5226   {
5227     detail::throw_exception<std::length_error>("max_size() == 0");
5228     // This eliminates any potential warnings
5229 #ifdef BOOST_STATIC_STRING_NO_NORETURN
5230     return *this;
5231 #endif
5232   }
5233 
5234   // Returns the size of data read from input iterator. Read data begins at data() + size() + 1.
5235   template<typename InputIterator>
5236   BOOST_STATIC_STRING_CPP14_CONSTEXPR
5237   size_type
5238   read_back(
5239     bool overwrite_null,
5240     InputIterator first,
5241     InputIterator last);
5242 
5243   BOOST_STATIC_STRING_CPP14_CONSTEXPR
5244   basic_static_string&
replace_unchecked(size_type pos,size_type n1,const_pointer s,size_type n2)5245   replace_unchecked(
5246     size_type pos,
5247     size_type n1,
5248     const_pointer s,
5249     size_type n2)
5250   {
5251     if (pos > size())
5252       detail::throw_exception<std::out_of_range>(
5253         "pos > size()");
5254     return replace_unchecked(data() + pos, data() + pos + capped_length(pos, n1), s, n2);
5255   }
5256 
5257   BOOST_STATIC_STRING_CPP14_CONSTEXPR
5258   basic_static_string&
5259   replace_unchecked(
5260     const_iterator i1,
5261     const_iterator i2,
5262     const_pointer s,
5263     size_type n2);
5264 
5265   BOOST_STATIC_STRING_CPP14_CONSTEXPR
5266   basic_static_string&
insert_unchecked(size_type index,const_pointer s,size_type count)5267   insert_unchecked(
5268     size_type index,
5269     const_pointer s,
5270     size_type count)
5271   {
5272     if (index > size())
5273       detail::throw_exception<std::out_of_range>(
5274         "index > size()");
5275     insert_unchecked(data() + index, s, count);
5276     return *this;
5277   }
5278 
5279   BOOST_STATIC_STRING_CPP14_CONSTEXPR
5280   iterator
5281   insert_unchecked(
5282     const_iterator pos,
5283     const_pointer s,
5284     size_type count);
5285 
5286   BOOST_STATIC_STRING_CPP14_CONSTEXPR
5287   basic_static_string&
assign_unchecked(const_pointer s,size_type count)5288   assign_unchecked(
5289     const_pointer s,
5290     size_type count) noexcept
5291   {
5292     this->set_size(count);
5293     traits_type::copy(data(), s, size() + 1);
5294     return *this;
5295   }
5296 
5297   BOOST_STATIC_STRING_CPP14_CONSTEXPR
5298   size_type
capped_length(size_type index,size_type length) const5299   capped_length(
5300     size_type index,
5301     size_type length) const
5302   {
5303     if (index > size())
5304       detail::throw_exception<std::out_of_range>(
5305         "index > size()");
5306     return (std::min)(size() - index, length);
5307   }
5308 };
5309 
5310 //------------------------------------------------------------------------------
5311 //
5312 // Non-member functions
5313 //
5314 //------------------------------------------------------------------------------
5315 
5316 template<
5317   std::size_t N, std::size_t M,
5318   typename CharT, typename Traits>
5319 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5320 inline
5321 bool
operator ==(const basic_static_string<N,CharT,Traits> & lhs,const basic_static_string<M,CharT,Traits> & rhs)5322 operator==(
5323   const basic_static_string<N, CharT, Traits>& lhs,
5324   const basic_static_string<M, CharT, Traits>& rhs)
5325 {
5326   return lhs.compare(rhs) == 0;
5327 }
5328 
5329 template<
5330   std::size_t N, std::size_t M,
5331   typename CharT, typename Traits>
5332 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5333 inline
5334 bool
operator !=(const basic_static_string<N,CharT,Traits> & lhs,const basic_static_string<M,CharT,Traits> & rhs)5335 operator!=(
5336   const basic_static_string<N, CharT, Traits>& lhs,
5337   const basic_static_string<M, CharT, Traits>& rhs)
5338 {
5339   return lhs.compare(rhs) != 0;
5340 }
5341 
5342 template<
5343   std::size_t N, std::size_t M,
5344   typename CharT, typename Traits>
5345 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5346 inline
5347 bool
operator <(const basic_static_string<N,CharT,Traits> & lhs,const basic_static_string<M,CharT,Traits> & rhs)5348 operator<(
5349   const basic_static_string<N, CharT, Traits>& lhs,
5350   const basic_static_string<M, CharT, Traits>& rhs)
5351 {
5352   return lhs.compare(rhs) < 0;
5353 }
5354 
5355 template<
5356   std::size_t N, std::size_t M,
5357   typename CharT, typename Traits>
5358 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5359 inline
5360 bool
operator <=(const basic_static_string<N,CharT,Traits> & lhs,const basic_static_string<M,CharT,Traits> & rhs)5361 operator<=(
5362   const basic_static_string<N, CharT, Traits>& lhs,
5363   const basic_static_string<M, CharT, Traits>& rhs)
5364 {
5365   return lhs.compare(rhs) <= 0;
5366 }
5367 
5368 template<
5369   std::size_t N, std::size_t M,
5370   typename CharT, typename Traits>
5371 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5372 inline
5373 bool
operator >(const basic_static_string<N,CharT,Traits> & lhs,const basic_static_string<M,CharT,Traits> & rhs)5374 operator>(
5375   const basic_static_string<N, CharT, Traits>& lhs,
5376   const basic_static_string<M, CharT, Traits>& rhs)
5377 {
5378   return lhs.compare(rhs) > 0;
5379 }
5380 
5381 template<
5382   std::size_t N, std::size_t M,
5383   typename CharT, typename Traits>
5384 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5385 inline
5386 bool
operator >=(const basic_static_string<N,CharT,Traits> & lhs,const basic_static_string<M,CharT,Traits> & rhs)5387 operator>=(
5388   const basic_static_string<N, CharT, Traits>& lhs,
5389   const basic_static_string<M, CharT, Traits>& rhs)
5390 {
5391   return lhs.compare(rhs) >= 0;
5392 }
5393 
5394 template<std::size_t N, typename CharT, typename Traits>
5395 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5396 inline
5397 bool
operator ==(const CharT * lhs,const basic_static_string<N,CharT,Traits> & rhs)5398 operator==(
5399   const CharT* lhs,
5400   const basic_static_string<N, CharT, Traits>& rhs)
5401 {
5402   return detail::lexicographical_compare<CharT, Traits>(
5403     lhs, Traits::length(lhs),
5404     rhs.data(), rhs.size()) == 0;
5405 }
5406 
5407 template<std::size_t N, typename CharT, typename Traits>
5408 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5409 inline
5410 bool
operator ==(const basic_static_string<N,CharT,Traits> & lhs,const CharT * rhs)5411 operator==(
5412   const basic_static_string<N, CharT, Traits>& lhs,
5413   const CharT* rhs)
5414 {
5415   return detail::lexicographical_compare<CharT, Traits>(
5416     lhs.data(), lhs.size(),
5417     rhs, Traits::length(rhs)) == 0;
5418 }
5419 
5420 template<std::size_t N, typename CharT, typename Traits>
5421 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5422 inline
5423 bool
operator !=(const CharT * lhs,const basic_static_string<N,CharT,Traits> & rhs)5424 operator!=(
5425   const CharT* lhs,
5426   const basic_static_string<N, CharT, Traits>& rhs)
5427 {
5428   return detail::lexicographical_compare<CharT, Traits>(
5429     lhs, Traits::length(lhs),
5430     rhs.data(), rhs.size()) != 0;
5431 }
5432 
5433 template<std::size_t N, typename CharT, typename Traits>
5434 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5435 inline
5436 bool
operator !=(const basic_static_string<N,CharT,Traits> & lhs,const CharT * rhs)5437 operator!=(
5438   const basic_static_string<N, CharT, Traits>& lhs,
5439   const CharT* rhs)
5440 {
5441   return detail::lexicographical_compare<CharT, Traits>(
5442     lhs.data(), lhs.size(),
5443     rhs, Traits::length(rhs)) != 0;
5444 }
5445 
5446 template<std::size_t N, typename CharT, typename Traits>
5447 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5448 inline
5449 bool
operator <(const CharT * lhs,const basic_static_string<N,CharT,Traits> & rhs)5450 operator<(
5451   const CharT* lhs,
5452   const basic_static_string<N, CharT, Traits>& rhs)
5453 {
5454   return detail::lexicographical_compare<CharT, Traits>(
5455     lhs, Traits::length(lhs),
5456     rhs.data(), rhs.size()) < 0;
5457 }
5458 
5459 template<std::size_t N, typename CharT, typename Traits>
5460 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5461 inline
5462 bool
operator <(const basic_static_string<N,CharT,Traits> & lhs,const CharT * rhs)5463 operator<(
5464   const basic_static_string<N, CharT, Traits>& lhs,
5465   const CharT* rhs)
5466 {
5467   return detail::lexicographical_compare<CharT, Traits>(
5468     lhs.data(), lhs.size(),
5469     rhs, Traits::length(rhs)) < 0;
5470 }
5471 
5472 template<std::size_t N, typename CharT, typename Traits>
5473 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5474 inline
5475 bool
operator <=(const CharT * lhs,const basic_static_string<N,CharT,Traits> & rhs)5476 operator<=(
5477   const CharT* lhs,
5478   const basic_static_string<N, CharT, Traits>& rhs)
5479 {
5480   return detail::lexicographical_compare<CharT, Traits>(
5481     lhs, Traits::length(lhs),
5482     rhs.data(), rhs.size()) <= 0;
5483 }
5484 
5485 template<std::size_t N, typename CharT, typename Traits>
5486 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5487 inline
5488 bool
operator <=(const basic_static_string<N,CharT,Traits> & lhs,const CharT * rhs)5489 operator<=(
5490   const basic_static_string<N, CharT, Traits>& lhs,
5491   const CharT* rhs)
5492 {
5493   return detail::lexicographical_compare<CharT, Traits>(
5494     lhs.data(), lhs.size(),
5495     rhs, Traits::length(rhs)) <= 0;
5496 }
5497 
5498 template<std::size_t N, typename CharT, typename Traits>
5499 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5500 inline
5501 bool
operator >(const CharT * lhs,const basic_static_string<N,CharT,Traits> & rhs)5502 operator>(
5503   const CharT* lhs,
5504   const basic_static_string<N, CharT, Traits>& rhs)
5505 {
5506   return detail::lexicographical_compare<CharT, Traits>(
5507     lhs, Traits::length(lhs),
5508     rhs.data(), rhs.size()) > 0;
5509 }
5510 
5511 template<std::size_t N, typename CharT, typename Traits>
5512 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5513 inline
5514 bool
operator >(const basic_static_string<N,CharT,Traits> & lhs,const CharT * rhs)5515 operator>(
5516   const basic_static_string<N, CharT, Traits>& lhs,
5517   const CharT* rhs)
5518 {
5519   return detail::lexicographical_compare<CharT, Traits>(
5520     lhs.data(), lhs.size(),
5521     rhs, Traits::length(rhs)) > 0;
5522 }
5523 
5524 template<std::size_t N, typename CharT, typename Traits>
5525 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5526 inline
5527 bool
operator >=(const CharT * lhs,const basic_static_string<N,CharT,Traits> & rhs)5528 operator>=(
5529   const CharT* lhs,
5530   const basic_static_string<N, CharT, Traits>& rhs)
5531 {
5532   return detail::lexicographical_compare<CharT, Traits>(
5533     lhs, Traits::length(lhs),
5534     rhs.data(), rhs.size()) >= 0;
5535 }
5536 
5537 template<std::size_t N, typename CharT, typename Traits>
5538 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5539 inline
5540 bool
operator >=(const basic_static_string<N,CharT,Traits> & lhs,const CharT * rhs)5541 operator>=(
5542   const basic_static_string<N, CharT, Traits>& lhs,
5543   const CharT* rhs)
5544 {
5545   return detail::lexicographical_compare<CharT, Traits>(
5546     lhs.data(), lhs.size(),
5547     rhs, Traits::length(rhs)) >= 0;
5548 }
5549 
5550 template<
5551   std::size_t N, std::size_t M,
5552   typename CharT, typename Traits>
5553 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5554 inline
5555 basic_static_string<N + M, CharT, Traits>
operator +(const basic_static_string<N,CharT,Traits> & lhs,const basic_static_string<M,CharT,Traits> & rhs)5556 operator+(
5557   const basic_static_string<N, CharT, Traits>& lhs,
5558   const basic_static_string<M, CharT, Traits>& rhs)
5559 {
5560   return basic_static_string<N + M, CharT, Traits>(lhs) += rhs;
5561 }
5562 
5563 template<std::size_t N, typename CharT, typename Traits>
5564 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5565 inline
5566 basic_static_string<N + 1, CharT, Traits>
operator +(const basic_static_string<N,CharT,Traits> & lhs,CharT rhs)5567 operator+(
5568   const basic_static_string<N, CharT, Traits>& lhs,
5569   CharT rhs)
5570 {
5571   return basic_static_string<N + 1, CharT, Traits>(lhs) += rhs;
5572 }
5573 
5574 template<std::size_t N, typename CharT, typename Traits>
5575 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5576 inline
5577 basic_static_string<N + 1, CharT, Traits>
operator +(CharT lhs,const basic_static_string<N,CharT,Traits> & rhs)5578 operator+(
5579   CharT lhs,
5580   const basic_static_string<N, CharT, Traits>& rhs)
5581 {
5582   // The cast to std::size_t is needed here since 0 is a null pointer constant
5583   return basic_static_string<N + 1, CharT, Traits>(rhs).insert(
5584     std::size_t(0), 1, lhs);
5585 }
5586 
5587 // Add a null terminated character array to a string.
5588 template<
5589   std::size_t N, std::size_t M,
5590   typename CharT, typename Traits>
5591 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5592 inline
5593 basic_static_string<N + M, CharT, Traits>
operator +(const basic_static_string<N,CharT,Traits> & lhs,const CharT (& rhs)[M])5594 operator+(
5595   const basic_static_string<N, CharT, Traits>& lhs,
5596   const CharT(&rhs)[M])
5597 {
5598   return basic_static_string<N + M, CharT, Traits>(lhs).append(+rhs);
5599 }
5600 
5601 // Add a string to a null terminated character array.
5602 template<
5603   std::size_t N, std::size_t M,
5604   typename CharT, typename Traits>
5605 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5606 inline
5607 basic_static_string<N + M, CharT, Traits>
operator +(const CharT (& lhs)[N],const basic_static_string<M,CharT,Traits> & rhs)5608 operator+(
5609   const CharT(&lhs)[N],
5610   const basic_static_string<M, CharT, Traits>& rhs)
5611 {
5612   // The cast to std::size_t is needed here since 0 is a null pointer constant
5613   return basic_static_string<N + M, CharT, Traits>(rhs).insert(
5614     std::size_t(0), +lhs);
5615 }
5616 
5617 //------------------------------------------------------------------------------
5618 //
5619 // swap
5620 //
5621 //------------------------------------------------------------------------------
5622 
5623 template<std::size_t N, typename CharT, typename Traits>
5624 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5625 inline
5626 void
swap(basic_static_string<N,CharT,Traits> & lhs,basic_static_string<N,CharT,Traits> & rhs)5627 swap(
5628   basic_static_string<N, CharT, Traits>& lhs,
5629   basic_static_string<N, CharT, Traits>& rhs)
5630 {
5631   lhs.swap(rhs);
5632 }
5633 
5634 template<
5635   std::size_t N, std::size_t M,
5636   typename CharT, typename Traits>
5637 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5638 inline
5639 void
swap(basic_static_string<N,CharT,Traits> & lhs,basic_static_string<M,CharT,Traits> & rhs)5640 swap(
5641   basic_static_string<N, CharT, Traits>& lhs,
5642   basic_static_string<M, CharT, Traits>& rhs)
5643 {
5644   lhs.swap(rhs);
5645 }
5646 
5647 //------------------------------------------------------------------------------
5648 //
5649 // Input/Output
5650 //
5651 //------------------------------------------------------------------------------
5652 
5653 template<std::size_t N, typename CharT, typename Traits>
5654 inline
5655 std::basic_ostream<CharT, Traits>&
operator <<(std::basic_ostream<CharT,Traits> & os,const basic_static_string<N,CharT,Traits> & s)5656 operator<<(
5657   std::basic_ostream<CharT, Traits>& os,
5658   const basic_static_string<N, CharT, Traits>& s)
5659 {
5660   return os << basic_string_view<CharT, Traits>(s.data(), s.size());
5661 }
5662 
5663 //------------------------------------------------------------------------------
5664 //
5665 // Numeric conversions
5666 //
5667 //------------------------------------------------------------------------------
5668 
5669 // Signed overloads have a + 2, one for the missing digit,
5670 // and one for the sign.
5671 
5672 // Unsigned overloads have a + 1, for the missing digit.
5673 
5674 // Floating point overloads have a + 4, for the sign
5675 // of the integral part, sign of the exponent, the 'e',
5676 // and the decimal.
5677 
5678 /// Converts `value` to a `static_string`
5679 static_string<std::numeric_limits<int>::digits10 + 2>
5680 inline
to_static_string(int value)5681 to_static_string(int value) noexcept
5682 {
5683   return detail::to_static_string_int_impl<
5684     std::numeric_limits<int>::digits10 + 2>(value);
5685 }
5686 
5687 /// Converts `value` to a `static_string`
5688 static_string<std::numeric_limits<long>::digits10 + 2>
5689 inline
to_static_string(long value)5690 to_static_string(long value) noexcept
5691 {
5692   return detail::to_static_string_int_impl<
5693     std::numeric_limits<long>::digits10 + 2>(value);
5694 }
5695 
5696 /// Converts `value` to a `static_string`
5697 static_string<std::numeric_limits<long long>::digits10 + 2>
5698 inline
to_static_string(long long value)5699 to_static_string(long long value) noexcept
5700 {
5701   return detail::to_static_string_int_impl<
5702     std::numeric_limits<long long>::digits10 + 2>(value);
5703 }
5704 
5705 /// Converts `value` to a `static_string`
5706 static_string<std::numeric_limits<unsigned int>::digits10 + 1>
5707 inline
to_static_string(unsigned int value)5708 to_static_string(unsigned int value) noexcept
5709 {
5710   return detail::to_static_string_int_impl<
5711     std::numeric_limits<unsigned int>::digits10 + 1>(value);
5712 }
5713 
5714 /// Converts `value` to a `static_string`
5715 static_string<std::numeric_limits<unsigned long>::digits10 + 1>
5716 inline
to_static_string(unsigned long value)5717 to_static_string(unsigned long value) noexcept
5718 {
5719   return detail::to_static_string_int_impl<
5720     std::numeric_limits<unsigned long>::digits10 + 1>(value);
5721 }
5722 
5723 /// Converts `value` to a `static_string`
5724 static_string<std::numeric_limits<unsigned long long>::digits10 + 1>
5725 inline
to_static_string(unsigned long long value)5726 to_static_string(unsigned long long value) noexcept
5727 {
5728   return detail::to_static_string_int_impl<
5729     std::numeric_limits<unsigned long long>::digits10 + 1>(value);
5730 }
5731 
5732 /// Converts `value` to a `static_string`
5733 static_string<std::numeric_limits<float>::max_digits10 + 4>
5734 inline
to_static_string(float value)5735 to_static_string(float value) noexcept
5736 {
5737   return detail::to_static_string_float_impl<
5738     std::numeric_limits<float>::max_digits10 + 4>(value);
5739 }
5740 
5741 /// Converts `value` to a `static_string`
5742 static_string<std::numeric_limits<double>::max_digits10 + 4>
5743 inline
to_static_string(double value)5744 to_static_string(double value) noexcept
5745 {
5746   return detail::to_static_string_float_impl<
5747     std::numeric_limits<double>::max_digits10 + 4>(value);
5748 }
5749 
5750 /// Converts `value` to a `static_string`
5751 static_string<std::numeric_limits<long double>::max_digits10 + 4>
5752 inline
to_static_string(long double value)5753 to_static_string(long double value) noexcept
5754 {
5755   return detail::to_static_string_float_impl<
5756     std::numeric_limits<long double>::max_digits10 + 4>(value);
5757 }
5758 
5759 /// Converts `value` to a `static_wstring`
5760 static_wstring<std::numeric_limits<int>::digits10 + 2>
5761 inline
to_static_wstring(int value)5762 to_static_wstring(int value) noexcept
5763 {
5764   return detail::to_static_wstring_int_impl<
5765     std::numeric_limits<int>::digits10 + 2>(value);
5766 }
5767 
5768 /// Converts `value` to a `static_wstring`
5769 static_wstring<std::numeric_limits<long>::digits10 + 2>
5770 inline
to_static_wstring(long value)5771 to_static_wstring(long value) noexcept
5772 {
5773   return detail::to_static_wstring_int_impl<
5774     std::numeric_limits<long>::digits10 + 2>(value);
5775 }
5776 
5777 /// Converts `value` to a `static_wstring`
5778 static_wstring<std::numeric_limits<long long>::digits10 + 2>
5779 inline
to_static_wstring(long long value)5780 to_static_wstring(long long value) noexcept
5781 {
5782   return detail::to_static_wstring_int_impl<
5783     std::numeric_limits<long long>::digits10 + 2>(value);
5784 }
5785 
5786 /// Converts `value` to a `static_wstring`
5787 static_wstring<std::numeric_limits<unsigned int>::digits10 + 1>
5788 inline
to_static_wstring(unsigned int value)5789 to_static_wstring(unsigned int value) noexcept
5790 {
5791   return detail::to_static_wstring_int_impl<
5792     std::numeric_limits<unsigned int>::digits10 + 1>(value);
5793 }
5794 
5795 /// Converts `value` to a `static_wstring`
5796 static_wstring<std::numeric_limits<unsigned long>::digits10 + 1>
5797 inline
to_static_wstring(unsigned long value)5798 to_static_wstring(unsigned long value) noexcept
5799 {
5800   return detail::to_static_wstring_int_impl<
5801     std::numeric_limits<unsigned long>::digits10 + 1>(value);
5802 }
5803 
5804 /// Converts `value` to a `static_wstring`
5805 static_wstring<std::numeric_limits<unsigned long long>::digits10 + 1>
5806 inline
to_static_wstring(unsigned long long value)5807 to_static_wstring(unsigned long long value) noexcept
5808 {
5809   return detail::to_static_wstring_int_impl<
5810     std::numeric_limits<unsigned long long>::digits10 + 1>(value);
5811 }
5812 
5813 /// Converts `value` to a `static_wstring`
5814 static_wstring<std::numeric_limits<float>::max_digits10 + 4>
5815 inline
to_static_wstring(float value)5816 to_static_wstring(float value) noexcept
5817 {
5818   return detail::to_static_wstring_float_impl<
5819     std::numeric_limits<float>::max_digits10 + 4>(value);
5820 }
5821 
5822 /// Converts `value` to a `static_wstring`
5823 static_wstring<std::numeric_limits<double>::max_digits10 + 4>
5824 inline
to_static_wstring(double value)5825 to_static_wstring(double value) noexcept
5826 {
5827   return detail::to_static_wstring_float_impl<
5828     std::numeric_limits<double>::max_digits10 + 4>(value);
5829 }
5830 
5831 /// Converts `value` to a `static_wstring`
5832 static_wstring<std::numeric_limits<long double>::max_digits10 + 4>
5833 inline
to_static_wstring(long double value)5834 to_static_wstring(long double value) noexcept
5835 {
5836   return detail::to_static_wstring_float_impl<
5837     std::numeric_limits<long double>::max_digits10 + 4>(value);
5838 }
5839 
5840 //------------------------------------------------------------------------------
5841 //
5842 // Deduction Guides
5843 //
5844 //------------------------------------------------------------------------------
5845 
5846 #ifdef BOOST_STATIC_STRING_USE_DEDUCT
5847 template<std::size_t N, typename CharT>
5848 basic_static_string(CharT(&)[N]) ->
5849   basic_static_string<N, CharT, std::char_traits<CharT>>;
5850 #endif
5851 
5852 //------------------------------------------------------------------------------
5853 //
5854 // Hashing
5855 //
5856 //------------------------------------------------------------------------------
5857 
5858 #ifndef BOOST_STATIC_STRING_STANDALONE
5859 /// hash_value overload for Boost.Container_Hash
5860 template <std::size_t N,
5861   typename CharT,
5862   typename Traits>
5863 std::size_t
hash_value(const basic_static_string<N,CharT,Traits> & str)5864 hash_value(
5865   const basic_static_string<N, CharT, Traits>& str)
5866 {
5867   return boost::hash_range(str.begin(), str.end());
5868 }
5869 #endif
5870 } // static_strings
5871 
5872 //------------------------------------------------------------------------------
5873 //
5874 // using Declarations
5875 //
5876 //------------------------------------------------------------------------------
5877 
5878 using static_strings::static_string;
5879 using static_strings::static_wstring;
5880 using static_strings::static_u16string;
5881 using static_strings::static_u32string;
5882 } // boost
5883 
5884 /// std::hash partial specialization for basic_static_string
5885 namespace std {
5886 
5887 template<std::size_t N, typename CharT, typename Traits>
5888 struct hash<
5889 #ifdef BOOST_STATIC_STRING_DOCS
5890   basic_static_string
5891 #else
5892   boost::static_strings::basic_static_string<N, CharT, Traits>
5893 #endif
5894   >
5895 {
5896   std::size_t
operator ()std::hash5897   operator()(
5898     const boost::static_strings::basic_static_string<N, CharT, Traits>& str) const noexcept
5899   {
5900 #ifndef BOOST_STATIC_STRING_STANDALONE
5901     return boost::hash_range(str.begin(), str.end());
5902 #else
5903     using view_type = typename
5904       boost::static_strings::basic_string_view<CharT, Traits>;
5905     return std::hash<view_type>()(view_type(str.data(), str.size()));
5906 #endif
5907   }
5908 };
5909 } // std
5910 
5911 //--------------------------------------------------------------------------
5912 //
5913 // Implementation
5914 //
5915 //--------------------------------------------------------------------------
5916 
5917 #ifndef BOOST_STATIC_STRING_DOCS
5918 namespace boost {
5919 namespace static_strings {
5920 
5921 template<std::size_t N, typename CharT, typename Traits>
5922 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5923 auto
5924 basic_static_string<N, CharT, Traits>::
assign(size_type count,value_type ch)5925 assign(
5926   size_type count,
5927   value_type ch) ->
5928     basic_static_string&
5929 {
5930   if (count > max_size())
5931     detail::throw_exception<std::length_error>(
5932       "count > max_size()");
5933   this->set_size(count);
5934   traits_type::assign(data(), size(), ch);
5935   return term();
5936 }
5937 
5938 template<std::size_t N, typename CharT, typename Traits>
5939 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5940 auto
5941 basic_static_string<N, CharT, Traits>::
assign(const_pointer s,size_type count)5942 assign(
5943   const_pointer s,
5944   size_type count) ->
5945     basic_static_string&
5946 {
5947   if (count > max_size())
5948     detail::throw_exception<std::length_error>(
5949       "count > max_size()");
5950   this->set_size(count);
5951   traits_type::move(data(), s, size());
5952   return term();
5953 }
5954 
5955 template<std::size_t N, typename CharT, typename Traits>
5956 template<typename InputIterator>
5957 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5958 auto
5959 basic_static_string<N, CharT, Traits>::
assign(InputIterator first,InputIterator last)5960 assign(
5961   InputIterator first,
5962   InputIterator last) ->
5963     typename std::enable_if<
5964       detail::is_input_iterator<InputIterator>::value,
5965         basic_static_string&>::type
5966 {
5967   auto ptr = data();
5968   for (std::size_t i = 0; first != last; ++first, ++ptr, ++i)
5969   {
5970     if (i >= max_size())
5971     {
5972       this->set_size(i);
5973       term();
5974       detail::throw_exception<std::length_error>("n > max_size()");
5975     }
5976     traits_type::assign(*ptr, *first);
5977   }
5978   this->set_size(ptr - data());
5979   return term();
5980 }
5981 
5982 template<std::size_t N, typename CharT, typename Traits>
5983 BOOST_STATIC_STRING_CPP14_CONSTEXPR
5984 auto
5985 basic_static_string<N, CharT, Traits>::
insert(const_iterator pos,size_type count,value_type ch)5986 insert(
5987   const_iterator pos,
5988   size_type count,
5989   value_type ch) ->
5990     iterator
5991 {
5992   const auto curr_size = size();
5993   const auto curr_data = data();
5994   if (count > max_size() - curr_size)
5995     detail::throw_exception<std::length_error>(
5996       "count > max_size() - curr_size");
5997   const auto index = pos - curr_data;
5998   traits_type::move(&curr_data[index + count], &curr_data[index], curr_size - index + 1);
5999   traits_type::assign(&curr_data[index], count, ch);
6000   this->set_size(curr_size + count);
6001   return &curr_data[index];
6002 }
6003 
6004 template<std::size_t N, typename CharT, typename Traits>
6005 template<typename ForwardIterator>
6006 BOOST_STATIC_STRING_CPP14_CONSTEXPR
6007 auto
6008 basic_static_string<N, CharT, Traits>::
insert(const_iterator pos,ForwardIterator first,ForwardIterator last)6009 insert(
6010   const_iterator pos,
6011   ForwardIterator first,
6012   ForwardIterator last) ->
6013     typename std::enable_if<
6014       detail::is_forward_iterator<
6015         ForwardIterator>::value, iterator>::type
6016 {
6017   const auto curr_size = size();
6018   const auto curr_data = data();
6019   const std::size_t count = detail::distance(first, last);
6020   const std::size_t index = pos - curr_data;
6021   const auto first_addr = &*first;
6022   if (count > max_size() - curr_size)
6023     detail::throw_exception<std::length_error>(
6024       "count > max_size() - curr_size");
6025   const bool inside = detail::ptr_in_range(curr_data, curr_data + curr_size, first_addr);
6026   if (!inside || (inside && (first_addr + count <= pos)))
6027   {
6028     traits_type::move(&curr_data[index + count], &curr_data[index], curr_size - index + 1);
6029     detail::copy_with_traits<Traits>(first, last, &curr_data[index]);
6030   }
6031   else
6032   {
6033     const size_type offset = first_addr - curr_data;
6034     traits_type::move(&curr_data[index + count], &curr_data[index], curr_size - index + 1);
6035     if (offset < index)
6036     {
6037       const size_type diff = index - offset;
6038       traits_type::copy(&curr_data[index], &curr_data[offset], diff);
6039       traits_type::copy(&curr_data[index + diff], &curr_data[index + count], count - diff);
6040     }
6041     else
6042     {
6043       traits_type::copy(&curr_data[index], &curr_data[offset + count], count);
6044     }
6045   }
6046   this->set_size(curr_size + count);
6047   return curr_data + index;
6048 }
6049 
6050 template<std::size_t N, typename CharT, typename Traits>
6051 template<typename InputIterator>
6052 BOOST_STATIC_STRING_CPP14_CONSTEXPR
6053 auto
6054 basic_static_string<N, CharT, Traits>::
insert(const_iterator pos,InputIterator first,InputIterator last)6055 insert(
6056   const_iterator pos,
6057   InputIterator first,
6058   InputIterator last) ->
6059     typename std::enable_if<
6060       detail::is_input_iterator<
6061         InputIterator>::value &&
6062           !detail::is_forward_iterator<
6063             InputIterator>::value, iterator>::type
6064 {
6065   const auto curr_size = size();
6066   const auto curr_data = data();
6067   const auto count = read_back(false, first, last);
6068   const std::size_t index = pos - curr_data;
6069   std::rotate(&curr_data[index], &curr_data[curr_size + 1], &curr_data[curr_size + count + 1]);
6070   this->set_size(curr_size + count);
6071   return curr_data + index;
6072 }
6073 
6074 template<std::size_t N, typename CharT, typename Traits>
6075 BOOST_STATIC_STRING_CPP14_CONSTEXPR
6076 auto
6077 basic_static_string<N, CharT, Traits>::
erase(const_iterator first,const_iterator last)6078 erase(
6079   const_iterator first,
6080   const_iterator last) ->
6081     iterator
6082 {
6083   const auto curr_data = data();
6084   const std::size_t index = first - curr_data;
6085   traits_type::move(&curr_data[index], last, (end() - last) + 1);
6086   this->set_size(size() - std::size_t(last - first));
6087   return curr_data + index;
6088 }
6089 
6090 template<std::size_t N, typename CharT, typename Traits>
6091 BOOST_STATIC_STRING_CPP14_CONSTEXPR
6092 void
6093 basic_static_string<N, CharT, Traits>::
push_back(value_type ch)6094 push_back(
6095   value_type ch)
6096 {
6097   const auto curr_size = size();
6098   if (curr_size >= max_size())
6099     detail::throw_exception<std::length_error>(
6100       "curr_size >= max_size()");
6101   traits_type::assign(data()[curr_size], ch);
6102   this->set_size(curr_size + 1);
6103   term();
6104 }
6105 
6106 template<std::size_t N, typename CharT, typename Traits>
6107 BOOST_STATIC_STRING_CPP14_CONSTEXPR
6108 auto
6109 basic_static_string<N, CharT, Traits>::
append(size_type count,value_type ch)6110 append(
6111   size_type count,
6112   value_type ch) ->
6113     basic_static_string&
6114 {
6115   const auto curr_size = size();
6116   if (count > max_size() - curr_size)
6117     detail::throw_exception<std::length_error>(
6118       "count > max_size() - size()");
6119   traits_type::assign(end(), count, ch);
6120   this->set_size(curr_size + count);
6121   return term();
6122 }
6123 
6124 template<std::size_t N, typename CharT, typename Traits>
6125 BOOST_STATIC_STRING_CPP14_CONSTEXPR
6126 auto
6127 basic_static_string<N, CharT, Traits>::
append(const_pointer s,size_type count)6128 append(
6129   const_pointer s,
6130   size_type count) ->
6131     basic_static_string&
6132 {
6133   const auto curr_size = size();
6134   if (count > max_size() - curr_size)
6135     detail::throw_exception<std::length_error>(
6136       "count > max_size() - size()");
6137   traits_type::copy(end(), s, count);
6138   this->set_size(curr_size + count);
6139   return term();
6140 }
6141 
6142 template<std::size_t N, typename CharT, typename Traits>
6143 BOOST_STATIC_STRING_CPP14_CONSTEXPR
6144 void
6145 basic_static_string<N, CharT, Traits>::
resize(size_type n,value_type c)6146 resize(size_type n, value_type c)
6147 {
6148   if (n > max_size())
6149     detail::throw_exception<std::length_error>(
6150       "n > max_size()");
6151   const auto curr_size = size();
6152   if(n > curr_size)
6153     traits_type::assign(data() + curr_size, n - curr_size, c);
6154   this->set_size(n);
6155   term();
6156 }
6157 
6158 template<std::size_t N, typename CharT, typename Traits>
6159 BOOST_STATIC_STRING_CPP14_CONSTEXPR
6160 void
6161 basic_static_string<N, CharT, Traits>::
swap(basic_static_string & s)6162 swap(basic_static_string& s) noexcept
6163 {
6164   const auto curr_size = size();
6165   basic_static_string tmp(s);
6166   s.set_size(curr_size);
6167   traits_type::copy(&s.data()[0], data(), curr_size + 1);
6168   this->set_size(tmp.size());
6169   traits_type::copy(data(), tmp.data(), size() + 1);
6170 }
6171 
6172 template<std::size_t N, typename CharT, typename Traits>
6173 template<std::size_t M>
6174 BOOST_STATIC_STRING_CPP14_CONSTEXPR
6175 void
6176 basic_static_string<N, CharT, Traits>::
swap(basic_static_string<M,CharT,Traits> & s)6177 swap(basic_static_string<M, CharT, Traits>& s)
6178 {
6179   const auto curr_size = size();
6180   if (curr_size > s.max_size())
6181     detail::throw_exception<std::length_error>(
6182       "curr_size > s.max_size()");
6183   if (s.size() > max_size())
6184     detail::throw_exception<std::length_error>(
6185       "s.size() > max_size()");
6186   basic_static_string tmp(s);
6187   s.set_size(curr_size);
6188   traits_type::copy(&s.data()[0], data(), curr_size + 1);
6189   this->set_size(tmp.size());
6190   traits_type::copy(data(), &tmp.data()[0], size() + 1);
6191 }
6192 
6193 template<std::size_t N, typename CharT, typename Traits>
6194 BOOST_STATIC_STRING_CPP14_CONSTEXPR
6195 auto
6196 basic_static_string<N, CharT, Traits>::
replace(const_iterator i1,const_iterator i2,size_type n,value_type c)6197 replace(
6198   const_iterator i1,
6199   const_iterator i2,
6200   size_type n,
6201   value_type c) ->
6202     basic_static_string<N, CharT, Traits>&
6203 {
6204   const auto curr_size = size();
6205   const auto curr_data = data();
6206   const std::size_t n1 = i2 - i1;
6207   if (n > max_size() || curr_size - n1 >= max_size() - n)
6208     detail::throw_exception<std::length_error>(
6209       "replaced string exceeds max_size()");
6210   const auto pos = i1 - curr_data;
6211   traits_type::move(&curr_data[pos + n], i2, (end() - i2) + 1);
6212   traits_type::assign(&curr_data[pos], n, c);
6213   this->set_size((curr_size - n1) + n);
6214   return *this;
6215 }
6216 
6217 template<std::size_t N, typename CharT, typename Traits>
6218 template<typename ForwardIterator>
6219 BOOST_STATIC_STRING_CPP14_CONSTEXPR
6220 auto
6221 basic_static_string<N, CharT, Traits>::
replace(const_iterator i1,const_iterator i2,ForwardIterator j1,ForwardIterator j2)6222 replace(
6223   const_iterator i1,
6224   const_iterator i2,
6225   ForwardIterator j1,
6226   ForwardIterator j2) ->
6227     typename std::enable_if<
6228       detail::is_forward_iterator<ForwardIterator>::value,
6229         basic_static_string<N, CharT, Traits>&>::type
6230 {
6231   const auto curr_size = size();
6232   const auto curr_data = data();
6233   const auto first_addr = &*j1;
6234   const std::size_t n1 = i2 - i1;
6235   const std::size_t n2 = detail::distance(j1, j2);
6236   const std::size_t pos = i1 - curr_data;
6237   if (n2 > max_size() || curr_size - (std::min)(n1, curr_size - pos) >= max_size() - n2)
6238     detail::throw_exception<std::length_error>(
6239       "replaced string exceeds max_size()");
6240   const bool inside = detail::ptr_in_range(curr_data, curr_data + curr_size, first_addr);
6241   if (inside && first_addr == i1 && n1 == n2)
6242     return *this;
6243   // Short circuit evaluation ensures that the pointer arithmetic is valid
6244   if (!inside || (inside && (first_addr + n2 <= i1)))
6245   {
6246     // source outside
6247     traits_type::move(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1);
6248     detail::copy_with_traits<Traits>(j1, j2, &curr_data[pos]);
6249   }
6250   else
6251   {
6252     // source inside
6253     const size_type offset = first_addr - curr_data;
6254     if (n2 >= n1)
6255     {
6256       // grow/unchanged
6257       const size_type diff = offset <= pos + n1 ? (std::min)((pos + n1) - offset, n2) : 0;
6258       // shift all right of splice point by n2 - n1 to the right
6259       traits_type::move(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1);
6260       // copy all before splice point
6261       traits_type::move(&curr_data[pos], &curr_data[offset], diff);
6262       // copy all after splice point
6263       traits_type::move(&curr_data[pos + diff], &curr_data[(offset - n1) + n2 + diff], n2 - diff);
6264     }
6265     else
6266     {
6267       // shrink
6268       // copy all elements into place
6269       traits_type::move(&curr_data[pos], &curr_data[offset], n2);
6270       // shift all elements after splice point left
6271       traits_type::move(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1);
6272     }
6273   }
6274   this->set_size((curr_size - n1) + n2);
6275   return *this;
6276 }
6277 
6278 template<std::size_t N, typename CharT, typename Traits>
6279 template<typename InputIterator>
6280 BOOST_STATIC_STRING_CPP14_CONSTEXPR
6281 auto
6282 basic_static_string<N, CharT, Traits>::
replace(const_iterator i1,const_iterator i2,InputIterator j1,InputIterator j2)6283 replace(
6284   const_iterator i1,
6285   const_iterator i2,
6286   InputIterator j1,
6287   InputIterator j2) ->
6288     typename std::enable_if<
6289       detail::is_input_iterator<
6290         InputIterator>::value &&
6291           !detail::is_forward_iterator<
6292             InputIterator>::value,
6293               basic_static_string<N, CharT, Traits>&>::type
6294 {
6295   const auto curr_size = size();
6296   const auto curr_data = data();
6297   const std::size_t n1 = detail::distance(i1, i2);
6298   const std::size_t n2 = read_back(false, j1, j2);
6299   const std::size_t pos = i1 - curr_data;
6300   // Rotate to the correct order. [i2, end] will now start with the replaced string,
6301   // continue to the existing string not being replaced, and end with a null terminator
6302   std::rotate(&curr_data[pos], &curr_data[curr_size + 1], &curr_data[curr_size + n2 + 1]);
6303   // Move everything from the end of the splice point to the end of the rotated string to
6304   // the begining of the splice point
6305   traits_type::move(&curr_data[pos + n2], &curr_data[pos + n2 + n1], ((curr_size - n1) + n2) - pos);
6306   this->set_size((curr_size - n1) + n2);
6307   return *this;
6308 }
6309 
6310 template<std::size_t N, typename CharT, typename Traits>
6311 BOOST_STATIC_STRING_CPP14_CONSTEXPR
6312 auto
6313 basic_static_string<N, CharT, Traits>::
find(const_pointer s,size_type pos,size_type n) const6314 find(
6315   const_pointer s,
6316   size_type pos,
6317   size_type n) const noexcept ->
6318     size_type
6319 {
6320   const auto curr_size = size();
6321   if (pos > curr_size || n > curr_size - pos)
6322     return npos;
6323   if (!n)
6324     return pos;
6325   const auto res = detail::search(data() + pos, data() + curr_size, s, s + n, traits_type::eq);
6326   return res == end() ? npos : detail::distance(data(), res);
6327 }
6328 
6329 template<std::size_t N, typename CharT, typename Traits>
6330 BOOST_STATIC_STRING_CPP14_CONSTEXPR
6331 auto
6332 basic_static_string<N, CharT, Traits>::
rfind(const_pointer s,size_type pos,size_type n) const6333 rfind(
6334   const_pointer s,
6335   size_type pos,
6336   size_type n) const noexcept ->
6337     size_type
6338 {
6339   const auto curr_size = size();
6340   const auto curr_data = data();
6341   if (curr_size < n)
6342     return npos;
6343   if (pos > curr_size - n)
6344     pos = curr_size - n;
6345   if (!n)
6346     return pos;
6347   for (auto sub = &curr_data[pos]; sub >= curr_data; --sub)
6348     if (!traits_type::compare(sub, s, n))
6349       return detail::distance(curr_data, sub);
6350   return npos;
6351 }
6352 
6353 template<std::size_t N, typename CharT, typename Traits>
6354 BOOST_STATIC_STRING_CPP14_CONSTEXPR
6355 auto
6356 basic_static_string<N, CharT, Traits>::
find_first_of(const_pointer s,size_type pos,size_type n) const6357 find_first_of(
6358   const_pointer s,
6359   size_type pos,
6360   size_type n) const noexcept ->
6361     size_type
6362 {
6363   const auto curr_data = data();
6364   if (pos >= size() || !n)
6365     return npos;
6366   const auto res = detail::find_first_of(&curr_data[pos], &curr_data[size()], s, &s[n], traits_type::eq);
6367   return res == end() ? npos : detail::distance(curr_data, res);
6368 }
6369 
6370 template<std::size_t N, typename CharT, typename Traits>
6371 BOOST_STATIC_STRING_CPP14_CONSTEXPR
6372 auto
6373 basic_static_string<N, CharT, Traits>::
find_last_of(const_pointer s,size_type pos,size_type n) const6374 find_last_of(
6375   const_pointer s,
6376   size_type pos,
6377   size_type n) const noexcept ->
6378     size_type
6379 {
6380   const auto curr_size = size();
6381   if (!n)
6382     return npos;
6383   if (pos >= curr_size)
6384     pos = 0;
6385   else
6386     pos = curr_size - (pos + 1);
6387   const auto res = detail::find_first_of(rbegin() + pos, rend(), s, &s[n], traits_type::eq);
6388   return res == rend() ? npos : curr_size - 1 - detail::distance(rbegin(), res);
6389 }
6390 
6391 template<std::size_t N, typename CharT, typename Traits>
6392 BOOST_STATIC_STRING_CPP14_CONSTEXPR
6393 auto
6394 basic_static_string<N, CharT, Traits>::
find_first_not_of(const_pointer s,size_type pos,size_type n) const6395 find_first_not_of(
6396   const_pointer s,
6397   size_type pos,
6398   size_type n) const noexcept ->
6399     size_type
6400 {
6401   if (pos >= size())
6402     return npos;
6403   if (!n)
6404     return pos;
6405   const auto res = detail::find_not_of<Traits>(data() + pos, data() + size(), s, n);
6406   return res == end() ? npos : detail::distance(data(), res);
6407 }
6408 
6409 template<std::size_t N, typename CharT, typename Traits>
6410 BOOST_STATIC_STRING_CPP14_CONSTEXPR
6411 auto
6412 basic_static_string<N, CharT, Traits>::
find_last_not_of(const_pointer s,size_type pos,size_type n) const6413 find_last_not_of(
6414   const_pointer s,
6415   size_type pos,
6416   size_type n) const noexcept ->
6417     size_type
6418 {
6419   const auto curr_size = size();
6420   if (pos >= curr_size)
6421     pos = curr_size - 1;
6422   if (!n)
6423     return pos;
6424   pos = curr_size - (pos + 1);
6425   const auto res = detail::find_not_of<Traits>(rbegin() + pos, rend(), s, n);
6426   return res == rend() ? npos : curr_size - 1 - detail::distance(rbegin(), res);
6427 }
6428 
6429 template<std::size_t N, typename CharT, typename Traits>
6430 template<typename InputIterator>
6431 BOOST_STATIC_STRING_CPP14_CONSTEXPR
6432 auto
6433 basic_static_string<N, CharT, Traits>::
read_back(bool overwrite_null,InputIterator first,InputIterator last)6434 read_back(
6435   bool overwrite_null,
6436   InputIterator first,
6437   InputIterator last) ->
6438     size_type
6439 {
6440   const auto curr_data = data();
6441   auto new_size = size();
6442   for (; first != last; ++first)
6443   {
6444     if (new_size >= max_size())
6445     {
6446       // if we overwrote the null terminator,
6447       // put it back
6448       if (overwrite_null)
6449         term();
6450       detail::throw_exception<std::length_error>(
6451         "count > max_size() - size()");
6452     }
6453     traits_type::assign(curr_data[new_size++ + (!overwrite_null)], *first);
6454   }
6455   return new_size - size();
6456 }
6457 
6458 template<std::size_t N, typename CharT, typename Traits>
6459 BOOST_STATIC_STRING_CPP14_CONSTEXPR
6460 auto
6461 basic_static_string<N, CharT, Traits>::
replace_unchecked(const_iterator i1,const_iterator i2,const_pointer s,size_type n2)6462 replace_unchecked(
6463   const_iterator i1,
6464   const_iterator i2,
6465   const_pointer s,
6466   size_type n2) ->
6467     basic_static_string&
6468 {
6469   const auto curr_data = data();
6470   const auto curr_size = size();
6471   const std::size_t pos = i1 - curr_data;
6472   const std::size_t n1 = i2 - i1;
6473   if (n2 > max_size() || curr_size - (std::min)(n1, curr_size - pos) >= max_size() - n2)
6474     detail::throw_exception<std::length_error>(
6475       "replaced string exceeds max_size()");
6476   traits_type::move(&curr_data[pos + n2], i2, (end() - i2) + 1);
6477   traits_type::copy(&curr_data[pos], s, n2);
6478   this->set_size((curr_size - n1) + n2);
6479   return *this;
6480 }
6481 
6482 template<std::size_t N, typename CharT, typename Traits>
6483 BOOST_STATIC_STRING_CPP14_CONSTEXPR
6484 auto
6485 basic_static_string<N, CharT, Traits>::
insert_unchecked(const_iterator pos,const_pointer s,size_type count)6486 insert_unchecked(
6487   const_iterator pos,
6488   const_pointer s,
6489   size_type count) ->
6490     iterator
6491 {
6492   const auto curr_data = data();
6493   const auto curr_size = size();
6494   if (count > max_size() - curr_size)
6495     detail::throw_exception<std::length_error>(
6496       "count > max_size() - curr_size");
6497   const std::size_t index = pos - curr_data;
6498   traits_type::move(&curr_data[index + count], pos, (end() - pos) + 1);
6499   traits_type::copy(&curr_data[index], s, count);
6500   this->set_size(curr_size + count);
6501   return curr_data + index;
6502 }
6503 } // static_strings
6504 } // boost
6505 #endif
6506 #endif
6507