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