scnlib  0.2.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
util.h
Go to the documentation of this file.
1 // Copyright 2017-2019 Elias Kosunen
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // This file is a part of scnlib:
16 // https://github.com/eliaskosunen/scnlib
17 
18 #ifndef SCN_DETAIL_UTIL_H
19 #define SCN_DETAIL_UTIL_H
20 
21 #include "config.h"
22 
23 #include <cstddef>
24 #include <limits>
25 #include <new>
26 #include <type_traits>
27 #include <utility>
28 
29 namespace scn {
31 
32  namespace detail {
33 #if SCN_HAS_VOID_T
34  template <typename... Ts>
35  using void_t = std::void_t<Ts...>;
36 #else
37  template <typename... Ts>
38  struct make_void {
39  using type = void;
40  };
41  template <typename... Ts>
42  using void_t = typename make_void<Ts...>::type;
43 #endif
44 
45  template <typename... T>
46  void valid_expr(T&&...);
47 
48  template <typename T>
49  struct remove_cvref {
50  using type = typename std::remove_cv<
52  };
53  template <typename T>
55 
56  // Stolen from range-v3
57  template <typename T>
58  struct static_const {
59  static constexpr T value{};
60  };
61  template <typename T>
62  constexpr T static_const<T>::value;
63 
64  template <size_t I>
65  struct priority_tag : priority_tag<I - 1> {
66  };
67  template <>
68  struct priority_tag<0> {
69  };
70 
71  template <typename T>
72  struct dependent_false : std::false_type {
73  };
74 
75  // Stolen from NanoRange
76  struct nonesuch {
77  nonesuch() = delete;
78  nonesuch(nonesuch const&) = delete;
79  nonesuch& operator=(const nonesuch&) = delete;
80  ~nonesuch() = delete;
81  };
82 
83  template <typename Void,
84  template <class...>
85  class Trait,
86  typename... Args>
87  struct _test {
88  using type = nonesuch;
89  };
90 
91  template <template <class...> class Trait, typename... Args>
92  struct _test<void_t<Trait<Args...>>, Trait, Args...> {
93  using type = Trait<Args...>;
94  };
95 
96  template <template <class...> class Trait, typename... Args>
97  using _test_t = typename _test<void, Trait, Args...>::type;
98 
99  template <typename Void,
100  template <class...>
101  class AliasT,
102  typename... Args>
103  struct exists_helper : std::false_type {
104  };
105 
106  template <template <class...> class AliasT, typename... Args>
107  struct exists_helper<void_t<AliasT<Args...>>, AliasT, Args...>
108  : std::true_type {
109  };
110 
111  template <template <class...> class AliasT, typename... Args>
112  struct exists : exists_helper<void, AliasT, Args...> {
113  };
114 
115  template <typename R,
116  typename... Args,
117  typename = decltype(&R::template _test_requires<Args...>)>
118  auto test_requires(R&) -> void;
119 
120  template <typename R, typename... Args>
121  using test_requires_t =
122  decltype(test_requires<R, Args...>(std::declval<R&>()));
123 
124  template <typename R, typename... Args>
125  struct _requires : exists<test_requires_t, R, Args...> {
126  };
127 
128  template <bool Expr>
130 
131  template <typename...>
133 
134  template <typename T, typename U>
135  struct _copy_cv {
136  using type = U;
137  };
138  template <typename T, typename U>
140  using type = typename std::add_const<U>::type;
141  };
142  template <typename T, typename U>
145  };
146  template <typename T, typename U>
148  using type = typename std::add_cv<U>::type;
149  };
150  template <typename T, typename U>
152 
153  template <typename T>
154  using _cref_t = typename std::add_lvalue_reference<
156 
157  template <typename T>
158  struct _rref_res {
159  using type = T;
160  };
161  template <typename T>
162  struct _rref_res<T&> {
164  };
165  template <typename T>
166  using _rref_res_t = typename _rref_res<T>::type;
167 
168  template <typename T, typename U>
169  using _cond_res_t =
170  decltype(std::declval<bool>() ? std::declval<T (&)()>()()
171  : std::declval<U (&)()>()());
172 
173  template <typename T, typename U>
175  };
176 
177  template <
178  typename T,
179  typename U,
180  typename C =
183  : std::enable_if<std::is_reference<C>::value, C> {
184  };
185  template <typename T, typename U>
186  using lvalue_scr_t =
188  template <typename T, typename U>
189  struct simple_common_reference<T&, U&>
191  };
192 
193  template <typename T,
194  typename U,
195  typename LCR = _test_t<lvalue_scr_t, T, U>,
196  typename C = _rref_res_t<LCR>>
198  : std::enable_if<std::is_convertible<T&&, C>::value &&
199  std::is_convertible<U&&, C>::value>::type {
200  };
201  template <typename T, typename U>
202  struct simple_common_reference<T&&, U&&>
204  };
205 
206  template <typename A,
207  typename B,
210  : std::enable_if<std::is_convertible<B&&, C>::value, C>::type {
211  };
212 
213  template <typename A, typename B>
214  struct simple_common_reference<A&, B&&>
216  };
217  template <typename A, typename B>
218  struct simple_common_reference<A&&, B&>
220  };
221  template <typename T, typename U>
224 
225  template <typename>
226  struct xref {
227  template <typename U>
228  using type = U;
229  };
230 
231  template <typename A>
232  struct xref<A&> {
233  template <typename U>
234  using type = typename std::add_lvalue_reference<
236  };
237 
238  template <typename A>
239  struct xref<A&&> {
240  template <typename U>
241  using type = typename std::add_rvalue_reference<
243  };
244 
245  template <typename A>
246  struct xref<const A> {
247  template <typename U>
248  using type = typename std::add_const<
250  };
251 
252  template <typename A>
253  struct xref<volatile A> {
254  template <typename U>
255  using type = typename std::add_volatile<
257  };
258 
259  template <typename A>
260  struct xref<const volatile A> {
261  template <typename U>
262  using type =
263  typename std::add_cv<typename xref<A>::template type<U>>::type;
264  };
265 
266  template <typename T,
267  typename U,
268  template <class>
269  class TQual,
270  template <class>
271  class UQual>
273  };
274 
275  template <typename...>
277  template <typename... Ts>
278  using get_common_reference_t =
279  typename get_common_reference<Ts...>::type;
280 
281  template <>
283  };
284  template <typename T0>
285  struct get_common_reference<T0> {
286  using type = T0;
287  };
288 
289  template <typename T, typename U>
290  struct has_simple_common_ref : exists<simple_common_reference_t, T, U> {
291  };
292  template <typename T, typename U>
293  using basic_common_ref_t =
298 
299  template <typename T, typename U>
300  struct has_basic_common_ref : exists<basic_common_ref_t, T, U> {
301  };
302  template <typename T, typename U>
303  struct has_cond_res : exists<_cond_res_t, T, U> {
304  };
305 
306  template <typename T, typename U, typename = void>
308  };
309  template <typename T, typename U>
311  T,
312  U,
313  typename std::enable_if<has_simple_common_ref<T, U>::value>::type>
314  : simple_common_reference<T, U> {
315  };
316  template <typename T, typename U>
318  T,
319  U,
320  typename std::enable_if<
321  has_basic_common_ref<T, U>::value &&
322  !has_simple_common_ref<T, U>::value>::type> {
324  };
325  template <typename T, typename U>
327  T,
328  U,
329  typename std::enable_if<
330  has_cond_res<T, U>::value &&
331  !has_basic_common_ref<T, U>::value &&
332  !has_simple_common_ref<T, U>::value>::type> {
334  };
335  template <typename T1, typename T2>
336  struct get_common_reference<T1, T2> : binary_common_ref<T1, T2> {
337  };
338 
339  template <typename Void, typename T1, typename T2, typename... Rest>
341  };
342  template <typename T1, typename T2, typename... Rest>
344  T1,
345  T2,
346  Rest...>
347  : get_common_reference<get_common_reference_t<T1, T2>, Rest...> {
348  };
349  template <typename T1, typename T2, typename... Rest>
350  struct get_common_reference<T1, T2, Rest...>
351  : multiple_common_reference<void, T1, T2, Rest...> {
352  };
353 
354  template <typename... Ts>
355  using get_common_type_t = typename get_common_type<Ts...>::type;
356 
357  template <typename T, typename U>
359  : std::integral_constant<
360  bool,
361  std::is_same<T, typename std::decay<T>::type>::value &&
362  std::is_same<U, typename std::decay<U>::type>::value> {
363  };
364 
365  template <typename T, typename U>
366  using ternary_return_t = typename std::decay<decltype(
367  false ? std::declval<T>() : std::declval<U>())>::type;
368 
369  template <typename, typename, typename = void>
371  };
372 
373  template <typename T, typename U>
375  T,
376  U,
377  typename std::enable_if<!_same_decayed<T, U>::value>::type>
378  : get_common_type<typename std::decay<T>::type,
379  typename std::decay<U>::type> {
380  };
381 
382  template <typename T, typename U>
384  T,
385  U,
386  typename std::enable_if<
387  _same_decayed<T, U>::value &&
388  exists<ternary_return_t, T, U>::value>::type> {
390  };
391 
392  template <typename T, typename U>
394  T,
395  U,
396  typename std::enable_if<
397  _same_decayed<T, U>::value &&
398  !exists<ternary_return_t, T, U>::value &&
399  exists<_cond_res_t, _cref_t<T>, _cref_t<U>>::value>::type> {
400  using type =
401  typename std::decay<_cond_res_t<_cref_t<T>, _cref_t<U>>>::type;
402  };
403 
404  template <>
405  struct get_common_type<> {
406  };
407 
408  template <typename T>
409  struct get_common_type<T> : get_common_type<T, T> {
410  };
411 
412  template <typename T, typename U>
413  struct get_common_type<T, U> : binary_common_type<T, U> {
414  };
415 
416  template <typename Void, typename...>
418  };
419 
420  template <typename T1, typename T2, typename... R>
422  T1,
423  T2,
424  R...>
425  : get_common_type<get_common_type_t<T1, T2>, R...> {
426  };
427 
428  template <typename T1, typename T2, typename... R>
429  struct get_common_type<T1, T2, R...>
430  : multiple_common_type<void, T1, T2, R...> {
431  };
432 
433  template <typename T>
434  constexpr typename std::decay<T>::type decay_copy(T&& t) noexcept(
435  noexcept(
436  static_cast<typename std::decay<T>::type>(std::forward<T>(t))))
437  {
438  return std::forward<T>(t);
439  }
440 
441  template <typename Integral>
442  SCN_CONSTEXPR14 int _max_digits(int base) noexcept
443  {
444  using lim = std::numeric_limits<Integral>;
445 
446  char base8_digits[8] = {3, 5, 0, 11, 0, 0, 0, 21};
447 
448  if (base == 10) {
449  return lim::digits10;
450  }
451  if (base == 8) {
452  return static_cast<int>(base8_digits[sizeof(Integral) - 1]);
453  }
454  if (base == lim::radix) {
455  return lim::digits;
456  }
457 
458  auto i = lim::max();
459 
460  Integral digits = 0;
461  while (i) {
462  i /= static_cast<Integral>(base);
463  digits++;
464  }
465  return static_cast<int>(digits);
466  }
467  template <typename Integral>
468  SCN_CONSTEXPR14 int max_digits(int base) noexcept
469  {
470  auto b = base == 0 ? 8 : base;
471  auto d = _max_digits<Integral>(b) +
472  (std::is_signed<Integral>::value ? 1 : 0);
473  if (base == 0) {
474  return d + 2; // accommondate for 0x/0o
475  }
476  return d;
477  }
478 
479  template <typename T>
480  constexpr std::pair<T, T> div(T l, T r) noexcept
481  {
482  return {l / r, l % r};
483  }
484 
485  template <typename T>
486  constexpr T* launder(T* p) noexcept
487  {
488 #if SCN_HAS_LAUNDER
489  return std::launder(p);
490 #else
491  return p;
492 #endif
493  }
494 
495  template <typename CharT>
496  CharT ascii_widen(char ch);
497  template <>
498  constexpr char ascii_widen(char ch)
499  {
500  return ch;
501  }
502  template <>
503  constexpr wchar_t ascii_widen(char ch)
504  {
505  return static_cast<wchar_t>(ch);
506  }
507 
508  template <typename T>
509  constexpr T max(T a, T b) noexcept
510  {
511  return (a < b) ? b : a;
512  }
513 
514  template <typename It>
515  SCN_CONSTEXPR14 It min_element(It first, It last)
516  {
517  if (first == last) {
518  return last;
519  }
520 
521  It smallest = first;
522  ++first;
523  for (; first != last; ++first) {
524  if (*first < *smallest) {
525  smallest = first;
526  }
527  }
528  return smallest;
529  }
530 
531  template <typename T>
532  constexpr T min(T a, T b) noexcept
533  {
534  return (b < a) ? b : a;
535  }
536  template <typename T>
537  SCN_CONSTEXPR14 T min(std::initializer_list<T> list) noexcept
538  {
539  return *min_element(list.begin(), list.end());
540  }
541 
542  template <typename CharT>
543  bool is_base_digit(CharT ch, int base)
544  {
545  if (base <= 10) {
546  return ch >= ascii_widen<CharT>('0') &&
547  ch <= ascii_widen<CharT>('0') + base - 1;
548  }
549  return is_base_digit(ch, 10) ||
550  (ch >= ascii_widen<CharT>('a') &&
551  ch <= ascii_widen<CharT>('a') + base - 1) ||
552  (ch >= ascii_widen<CharT>('A') &&
553  ch <= ascii_widen<CharT>('A') + base - 1);
554  }
555 
556  template <typename T>
558  public:
559  using element_type = T;
560  using pointer = T*;
561 
562  constexpr unique_ptr() noexcept = default;
563  constexpr unique_ptr(std::nullptr_t) noexcept {}
564 
565  constexpr explicit unique_ptr(pointer p) noexcept : m_ptr(p) {}
566 
567  template <
568  typename U,
569  typename std::enable_if<
570  std::is_convertible<U*, pointer>::value>::type* = nullptr>
572  : m_ptr(std::move(u.get()))
573  {
574  u.reset();
575  }
576 
577  unique_ptr(const unique_ptr&) = delete;
578  unique_ptr& operator=(const unique_ptr&) = delete;
579 
581  : m_ptr(std::move(p.m_ptr))
582  {
583  p.m_ptr = nullptr;
584  }
586  {
587  if (m_ptr) {
588  delete m_ptr;
589  }
590  m_ptr = p.m_ptr;
591  p.m_ptr = nullptr;
592  return *this;
593  }
594 
595  ~unique_ptr() noexcept
596  {
597  if (m_ptr) {
598  delete m_ptr;
599  }
600  }
601 
602  constexpr explicit operator bool() const noexcept
603  {
604  return get() != nullptr;
605  }
606 
607  constexpr pointer get() const noexcept
608  {
609  return m_ptr;
610  }
611 
612  constexpr pointer operator->() const noexcept
613  {
614  return m_ptr;
615  }
617  const
618  {
619  return *m_ptr;
620  }
621 
623  {
624  m_ptr = nullptr;
625  }
626 
627  private:
628  pointer m_ptr{nullptr};
629  };
630 
632  SCN_CLANG_IGNORE("-Wpadded")
633 
634  template <typename T, typename... Args>
635  unique_ptr<T> make_unique(Args&&... a)
636  {
637  return unique_ptr<T>(new T(std::forward<Args>(a)...));
638  }
639 
640  template <typename T, std::size_t N>
641  struct array {
642  static_assert(N > 0, "zero-sized array not supported");
643 
644  using value_type = T;
645  using size_type = std::size_t;
646  using difference_type = std::ptrdiff_t;
647  using reference = T&;
648  using const_reference = const T&;
649  using pointer = T*;
650  using const_pointer = const T*;
651  using iterator = pointer;
653 
655  {
656  SCN_EXPECT(i < size());
657  return m_data[i];
658  }
660  {
661  SCN_EXPECT(i < size());
662  return m_data[i];
663  }
664 
666  {
667  return m_data;
668  }
669  constexpr const_iterator begin() const noexcept
670  {
671  return m_data;
672  }
673  constexpr const_iterator cbegin() const noexcept
674  {
675  return m_data;
676  }
677 
679  {
680  return m_data + N;
681  }
682  constexpr const_iterator end() const noexcept
683  {
684  return m_data + N;
685  }
686  constexpr const_iterator cend() const noexcept
687  {
688  return m_data + N;
689  }
690 
692  {
693  return m_data;
694  }
695  constexpr const_pointer data() const noexcept
696  {
697  return m_data;
698  }
699 
700  constexpr size_type size() const noexcept
701  {
702  return N;
703  }
704 
705  T m_data[N];
706  };
707 
708  template <typename T>
710  public:
711  using value_type = T;
712  using pointer = T*;
713  using storage_type = unsigned char[sizeof(T)];
714 
715  constexpr erased_storage() noexcept = default;
716 
717  erased_storage(T val) noexcept(
718  std::is_nothrow_move_constructible<T>::value)
719  : m_ptr(::new (static_cast<void*>(&m_data)) T(std::move(val)))
720  {
721  }
722 
724  : m_ptr(other ? ::new (static_cast<void*>(&m_data))
725  T(other.get())
726  : nullptr)
727  {
728  }
730  {
731  _destruct();
732  if (other) {
733  m_ptr = ::new (static_cast<void*>(&m_data)) T(other.get());
734  }
735  return *this;
736  }
737 
738  erased_storage(erased_storage&& other) noexcept
739  : m_ptr(other ? ::new (static_cast<void*>(&m_data))
740  T(std::move(other.get()))
741  : nullptr)
742  {
743  other.m_ptr = nullptr;
744  }
746  {
747  _destruct();
748  if (other) {
749  m_ptr = ::new (static_cast<void*>(&m_data))
750  T(std::move(other.get()));
751  other.m_ptr = nullptr;
752  }
753  return *this;
754  }
755 
756  ~erased_storage() noexcept
757  {
758  _destruct();
759  }
760 
761  constexpr bool has_value() const noexcept
762  {
763  return m_ptr != nullptr;
764  }
765  constexpr explicit operator bool() const noexcept
766  {
767  return has_value();
768  }
769 
770  SCN_CONSTEXPR14 T& get() noexcept
771  {
772  SCN_EXPECT(has_value());
773  return _get();
774  }
775  SCN_CONSTEXPR14 const T& get() const noexcept
776  {
777  SCN_EXPECT(has_value());
778  return _get();
779  }
780 
782  {
783  SCN_EXPECT(has_value());
784  return _get();
785  }
786  SCN_CONSTEXPR14 const T& operator*() const noexcept
787  {
788  SCN_EXPECT(has_value());
789  return _get();
790  }
791 
793  {
794  return m_ptr;
795  }
796  SCN_CONSTEXPR14 const T* operator->() const noexcept
797  {
798  return m_ptr;
799  }
800 
801  private:
802  void _destruct()
803  {
804  if (m_ptr) {
805  _get().~T();
806  }
807  m_ptr = nullptr;
808  }
809  static pointer _toptr(storage_type& data)
810  {
812  reinterpret_cast<T*>(std::addressof(data)));
813  }
814  SCN_CONSTEXPR14 T& _get() noexcept
815  {
816  return *m_ptr;
817  }
818  SCN_CONSTEXPR14 const T& _get() const noexcept
819  {
820  return *m_ptr;
821  }
822 
823  alignas(T) storage_type m_data{};
824  pointer m_ptr{nullptr};
825  };
826 
828  } // namespace detail
829 
830  template <typename T>
831  class wrap_default {
832  public:
833  using value_type = T;
835 
836  wrap_default() = default;
837 
838  wrap_default(value_type&& val) : m_storage(std::move(val)) {}
840  {
841  m_storage = storage_type(std::move(val));
842  return *this;
843  }
844 
845  constexpr bool has_value() const noexcept
846  {
847  return m_storage.operator bool();
848  }
849  constexpr explicit operator bool() const noexcept
850  {
851  return has_value();
852  }
853 
854  SCN_CONSTEXPR14 T& get() noexcept
855  {
856  return m_storage.get();
857  }
858  SCN_CONSTEXPR14 const T& get() const noexcept
859  {
860  return m_storage.get();
861  }
862 
864  {
865  return get();
866  }
867  SCN_CONSTEXPR14 const T& operator*() const noexcept
868  {
869  return get();
870  }
871 
873  {
874  return m_storage.operator->();
875  }
876  SCN_CONSTEXPR14 const T* operator->() const noexcept
877  {
878  return m_storage.operator->();
879  }
880 
881  private:
882  storage_type m_storage;
883  };
884 
886 } // namespace scn
887 
888 #endif // SCN_DETAIL_UTIL_H
constexpr const_pointer data() const noexcept
Definition: util.h:695
const_pointer const_iterator
Definition: util.h:652
SCN_CONSTEXPR14 const T & operator*() const noexcept
Definition: util.h:867
const T * const_pointer
Definition: util.h:650
wrap_default(value_type &&val)
Definition: util.h:838
typename make_void< Ts...>::type void_t
Definition: util.h:42
decltype(std::declval< bool >()?std::declval< T(&)()>()():std::declval< U(&)()>()()) _cond_res_t
Definition: util.h:171
typename std::add_volatile< U >::type type
Definition: util.h:144
typename std::add_const< typename xref< A >::template type< U >>::type type
Definition: util.h:249
unique_ptr & operator=(unique_ptr &&p) noexcept
Definition: util.h:585
SCN_CLANG_PUSH unique_ptr< T > make_unique(Args &&...a)
Definition: util.h:635
typename std::add_rvalue_reference< typename xref< A >::template type< U >>::type type
Definition: util.h:242
wrap_default & operator=(value_type &&val)
Definition: util.h:839
constexpr pointer operator->() const noexcept
Definition: util.h:612
#define SCN_END_NAMESPACE
Definition: config.h:401
SCN_CONSTEXPR14 T * operator->() noexcept
Definition: util.h:792
typename std::enable_if< Expr, int >::type requires_expr
Definition: util.h:129
constexpr const_iterator cbegin() const noexcept
Definition: util.h:673
typename std::add_const< U >::type type
Definition: util.h:140
pointer iterator
Definition: util.h:651
typename remove_cvref< T >::type remove_cvref_t
Definition: util.h:54
typename std::add_cv< U >::type type
Definition: util.h:148
typename _test< void, Trait, Args...>::type _test_t
Definition: util.h:97
typename std::add_volatile< typename xref< A >::template type< U >>::type type
Definition: util.h:256
decltype(test_requires< R, Args...>(std::declval< R & >())) test_requires_t
Definition: util.h:122
constexpr size_type size() const noexcept
Definition: util.h:700
SCN_CONSTEXPR14 int max_digits(int base) noexcept
Definition: util.h:468
constexpr const_iterator begin() const noexcept
Definition: util.h:669
erased_storage(erased_storage &&other) noexcept
Definition: util.h:738
typename std::add_lvalue_reference< typename xref< A >::template type< U >>::type type
Definition: util.h:235
typename lvalue_simple_common_reference< T, U >::type lvalue_scr_t
Definition: util.h:187
constexpr std::pair< T, T > div(T l, T r) noexcept
Definition: util.h:480
SCN_CONSTEXPR14 T & operator*() noexcept
Definition: util.h:781
constexpr unique_ptr(pointer p) noexcept
Definition: util.h:565
SCN_CONSTEXPR14 iterator end() noexcept
Definition: util.h:678
constexpr std::add_lvalue_reference< T >::type operator*() const
Definition: util.h:616
#define SCN_CLANG_IGNORE(x)
Definition: config.h:144
constexpr T max(T a, T b) noexcept
Definition: util.h:509
bool is_base_digit(CharT ch, int base)
Definition: util.h:543
std::size_t size_type
Definition: util.h:645
SCN_CONSTEXPR14 const T * operator->() const noexcept
Definition: util.h:796
typename _rref_res< T >::type _rref_res_t
Definition: util.h:166
typename std::add_lvalue_reference< const typename std::remove_reference< T >::type >::type _cref_t
Definition: util.h:155
SCN_CONSTEXPR14 unique_ptr(unique_ptr< U > &&u) noexcept
Definition: util.h:571
nonesuch & operator=(const nonesuch &)=delete
wrap_default()=default
SCN_CONSTEXPR14 pointer data() noexcept
Definition: util.h:691
SCN_CONSTEXPR14 const T & operator*() const noexcept
Definition: util.h:786
typename simple_common_reference< T, U >::type simple_common_reference_t
Definition: util.h:223
#define SCN_CLANG_POP
Definition: config.h:143
typename std::add_cv< typename xref< A >::template type< U >>::type type
Definition: util.h:263
typename std::remove_reference< T >::type && type
Definition: util.h:163
constexpr T * launder(T *p) noexcept
Definition: util.h:486
constexpr T min(T a, T b) noexcept
Definition: util.h:532
constexpr std::decay< T >::type decay_copy(T &&t) noexcept(noexcept(static_cast< typename std::decay< T >::type >(std::forward< T >(t))))
Definition: util.h:434
const T & const_reference
Definition: util.h:648
SCN_CONSTEXPR14 T & get() noexcept
Definition: util.h:770
typename std::decay< decltype(false?std::declval< T >():std::declval< U >())>::type ternary_return_t
Definition: util.h:367
#define SCN_TRIVIAL_ABI
Definition: config.h:266
constexpr const_iterator end() const noexcept
Definition: util.h:682
~unique_ptr() noexcept
Definition: util.h:595
auto test_requires(R &) -> void
~erased_storage() noexcept
Definition: util.h:756
SCN_CONSTEXPR14 iterator begin() noexcept
Definition: util.h:665
#define SCN_BEGIN_NAMESPACE
Definition: config.h:400
typename basic_common_reference< remove_cvref_t< T >, remove_cvref_t< U >, xref< T >::template type, xref< U >::template type >::type basic_common_ref_t
Definition: util.h:297
SCN_CONSTEXPR14 reference operator[](size_type i)
Definition: util.h:654
constexpr const_reference operator[](size_type i) const
Definition: util.h:659
erased_storage & operator=(const erased_storage &other)
Definition: util.h:729
CharT ascii_widen(char ch)
Definition: util.h:498
std::ptrdiff_t difference_type
Definition: util.h:646
erased_storage & operator=(erased_storage &&other) noexcept
Definition: util.h:745
typename _copy_cv< T, U >::type _copy_cv_t
Definition: util.h:151
SCN_CONSTEXPR14 const T * operator->() const noexcept
Definition: util.h:876
detail::erased_storage< T > storage_type
Definition: util.h:834
SCN_CONSTEXPR14 void reset()
Definition: util.h:622
constexpr bool has_value() const noexcept
Definition: util.h:845
typename std::remove_cv< typename std::remove_reference< T >::type >::type type
Definition: util.h:51
typename get_common_type< Ts...>::type get_common_type_t
Definition: util.h:355
void valid_expr(T &&...)
erased_storage(const erased_storage &other)
Definition: util.h:723
unsigned char[sizeof(T)] storage_type
Definition: util.h:713
auto get(const subrange< I, S, K > &s) -> decltype(_subrange_get_impl< N >::get(s))
Definition: ranges.h:1185
SCN_CONSTEXPR14 T * operator->() noexcept
Definition: util.h:872
SCN_CONSTEXPR14 int _max_digits(int base) noexcept
Definition: util.h:442
SCN_CONSTEXPR14 It min_element(It first, It last)
Definition: util.h:515
SCN_CONSTEXPR14 unique_ptr(unique_ptr &&p) noexcept
Definition: util.h:580
constexpr const_iterator cend() const noexcept
Definition: util.h:686
#define SCN_EXPECT(cond)
Definition: config.h:396
#define SCN_CLANG_PUSH
Definition: config.h:142
#define SCN_CONSTEXPR14
Definition: config.h:240
SCN_CONSTEXPR14 T & operator*() noexcept
Definition: util.h:863
constexpr bool has_value() const noexcept
Definition: util.h:761
typename get_common_reference< Ts...>::type get_common_reference_t
Definition: util.h:279