scnlib  0.2.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ranges.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 // The contents of this file are essentially stolen from NanoRange,
19 // except the code has been ported to C++11
20 // https://github.com/tcbrindle/NanoRange
21 // Copyright (c) 2018 Tristan Brindle
22 // Distributed under the Boost Software License, Version 1.0
23 
24 #ifndef SCN_DETAIL_RANGES_H
25 #define SCN_DETAIL_RANGES_H
26 
27 #include "string_view.h"
28 
29 #include <iterator>
30 
31 namespace scn {
33 
34  namespace detail {
35  namespace ranges {
36  // iterator_category is span.h
37 
38  template <typename T>
40 
41  template <typename T, typename = void>
43  };
44  template <typename T>
45  struct _iterator_category<T*>
46  : std::enable_if<std::is_object<T>::value,
48  };
49  template <typename T>
50  struct _iterator_category<const T> : iterator_category<T> {
51  };
52  template <typename T>
54  void_t<typename T::iterator_category>> {
55  using type = typename T::iterator_category;
56  };
57 
58  template <typename T>
60  };
61  template <typename T>
63 
64  template <typename T>
65  using iter_reference_t = decltype(*std::declval<T&>());
66 
67  // iter_difference_t
68  template <typename>
70 
71  struct _empty {
72  };
73 
74  template <typename T>
76  using difference_type = T;
77  };
78  template <typename, typename = void>
80  };
81 
82  template <>
84  };
85  template <typename T>
87  : std::conditional<std::is_object<T>::value,
89  _empty>::type {
90  };
91  template <typename I>
93  : incrementable_traits<typename std::decay<I>::type> {
94  };
95 
96  template <typename, typename = void>
97  struct _has_member_difference_type : std::false_type {
98  };
99  template <typename T>
101  T,
102  void_t<typename T::difference_type>> : std::true_type {
103  };
104 
105  template <typename T>
107  T,
108  typename std::enable_if<
109  _has_member_difference_type<T>::value>::type> {
110  using difference_type = typename T::difference_type;
111  };
112  template <typename T>
114  T,
115  typename std::enable_if<
116  !std::is_pointer<T>::value &&
117  !_has_member_difference_type<T>::value &&
118  std::is_integral<decltype(
119  std::declval<const T&>() -
120  std::declval<const T&>())>::value>::type>
121  : _with_difference_type<typename std::make_signed<decltype(
122  std::declval<T>() - std::declval<T>())>::type> {
123  };
124  template <typename T>
126  };
127 
128  template <typename T>
129  using iter_difference_t =
131 
132  // iter_value_t
133  template <typename>
135 
136  template <typename T>
138  using value_type = T;
139  };
140  template <typename, typename = void>
142  };
143 
144  template <typename T>
146  : std::conditional<
147  std::is_object<T>::value,
149  _empty>::type {
150  };
151 
152  template <typename I>
154  I,
155  typename std::enable_if<std::is_array<I>::value>::type>
156  : readable_traits<typename std::decay<I>::type> {
157  };
158 
159  template <typename I>
161  const I,
162  typename std::enable_if<!std::is_array<I>::value>::type>
163  : readable_traits<typename std::decay<I>::type> {
164  };
165 
166  template <typename T, typename V = typename T::value_type>
168  : std::conditional<std::is_object<V>::value,
169  _with_value_type<V>,
170  _empty>::type {
171  };
172 
173  template <typename T, typename E = typename T::element_type>
175  : std::conditional<
176  std::is_object<E>::value,
177  _with_value_type<typename std::remove_cv<E>::type>,
178  _empty>::type {
179  };
180 
181  template <typename T>
182  using _member_value_type_t = typename T::value_type;
183 
184  template <typename T>
185  struct _has_member_value_type : exists<_member_value_type_t, T> {
186  };
187 
188  template <typename T>
189  using _member_element_type_t = typename T::element_type;
190 
191  template <typename T>
193  : exists<_member_element_type_t, T> {
194  };
195 
196  template <typename T>
198  T,
199  typename std::enable_if<
200  _has_member_value_type<T>::value &&
201  !_has_member_element_type<T>::value>::type>
202  : _member_value_type<T> {
203  };
204 
205  template <typename T>
207  T,
208  typename std::enable_if<
209  _has_member_element_type<T>::value &&
210  !_has_member_value_type<T>::value>::type>
211  : _member_element_type<T> {
212  };
213 
214  template <typename T>
216  T,
217  typename std::enable_if<
218  _has_member_element_type<T>::value &&
219  _has_member_value_type<T>::value>::type> {
220  };
221 
222  template <typename T>
224  };
225 
226  template <typename T>
228 
229  // sentinel_for
231  template <typename S, typename I>
232  auto _test_requires(S s, I i)
233  -> decltype(scn::detail::valid_expr(*i, i == s, i != s));
234  };
235  template <typename S, typename I>
237  : std::integral_constant<
238  bool,
239  std::is_default_constructible<S>::value &&
240  std::is_copy_constructible<S>::value &&
241  _requires<_sentinel_for_concept, S, I>::value> {
242  };
243 
244  // sized_sentinel_for
246  template <typename S, typename I>
247  auto _test_requires(const S& s, const I& i) -> decltype(
248  requires_expr<std::is_same<decltype(s - i),
250  requires_expr<std::is_same<decltype(i - s),
252  };
253  template <typename S, typename I>
255  : std::integral_constant<
256  bool,
257  _requires<_sized_sentinel_for_concept, S, I>::value &&
258  sentinel_for<S, I>::value> {
259  };
260  template <typename S>
261  struct sized_sentinel_for<S, void*> : std::false_type {
262  };
263  template <typename I>
264  struct sized_sentinel_for<void*, I> : std::false_type {
265  };
266  template <>
267  struct sized_sentinel_for<void*, void*> : std::false_type {
268  };
269 
270  // begin
271  namespace _begin {
272  template <typename T>
273  void begin(T&&) = delete;
274  template <typename T>
275  void begin(std::initializer_list<T>&&) = delete;
276 
277  struct fn {
278  private:
279  template <typename T, std::size_t N>
280  static SCN_CONSTEXPR14 void impl(T(&&)[N],
281  priority_tag<3>) = delete;
282 
283  template <typename T, std::size_t N>
284  static SCN_CONSTEXPR14 auto impl(T (&t)[N],
285  priority_tag<3>) noexcept
286  -> decltype((t) + 0)
287  {
288  return (t) + 0;
289  }
290 
291  template <typename C>
292  static SCN_CONSTEXPR14 auto impl(basic_string_view<C> sv,
293  priority_tag<2>) noexcept
294  -> decltype(sv.begin())
295  {
296  return sv.begin();
297  }
298 
299  template <typename T>
300  static SCN_CONSTEXPR14 auto
301  impl(T& t, priority_tag<1>) noexcept(
302  noexcept(decay_copy(t.begin())))
303  -> decltype(decay_copy(t.begin()))
304  {
305  return decay_copy(t.begin());
306  }
307 
308  template <typename T>
309  static SCN_CONSTEXPR14 auto
310  impl(T&& t, priority_tag<0>) noexcept(
311  noexcept(decay_copy(begin(std::forward<T>(t)))))
312  -> decltype(decay_copy(begin(std::forward<T>(t))))
313  {
314  return decay_copy(begin(std::forward<T>(t)));
315  }
316 
317  public:
318  template <typename T>
319  SCN_CONSTEXPR14 auto operator()(T&& t) const
320  noexcept(noexcept(fn::impl(std::forward<T>(t),
321  priority_tag<3>{})))
322  -> decltype(fn::impl(std::forward<T>(t),
323  priority_tag<3>{}))
324  {
325  return fn::impl(std::forward<T>(t), priority_tag<3>{});
326  }
327  };
328  } // namespace _begin
329  namespace {
330  constexpr auto& begin = static_const<_begin::fn>::value;
331  }
332 
333  // end
334  namespace _end {
335  template <typename T>
336  void end(T&&) = delete;
337  template <typename T>
338  void end(std::initializer_list<T>&&) = delete;
339 
340  struct fn {
341  private:
342  template <typename T, std::size_t N>
343  static constexpr void impl(T(&&)[N],
344  priority_tag<2>) = delete;
345 
346  template <typename T, std::size_t N>
347  static constexpr auto impl(T (&t)[N],
348  priority_tag<2>) noexcept
349  -> decltype((t) + N)
350  {
351  return (t) + N;
352  }
353 
354  template <typename C>
355  static constexpr auto impl(basic_string_view<C> sv,
356  priority_tag<2>) noexcept
357  -> decltype(sv.end())
358  {
359  return sv.end();
360  }
361 
362  template <
363  typename T,
364  typename S =
365  decltype(decay_copy(std::declval<T&>().end())),
366  typename I = decltype(
367  ::scn::detail::ranges::begin(std::declval<T&>()))>
368  static constexpr auto impl(T& t, priority_tag<1>) noexcept(
369  noexcept(decay_copy(t.end())))
370  -> decltype(decay_copy(t.end()))
371  {
372  return decay_copy(t.end());
373  }
374 
375  template <
376  typename T,
377  typename S =
378  decltype(decay_copy(end(std::declval<T>()))),
379  typename I = decltype(
380  ::scn::detail::ranges::begin(std::declval<T>()))>
381  static constexpr auto impl(T& t, priority_tag<0>) noexcept(
382  noexcept(decay_copy(end(std::forward<T>(t))))) -> S
383  {
384  return decay_copy(end(std::forward<T>(t)));
385  }
386 
387  public:
388  template <typename T>
389  constexpr auto operator()(T&& t) const
390  noexcept(noexcept(fn::impl(std::forward<T>(t),
391  priority_tag<2>{})))
392  -> decltype(fn::impl(std::forward<T>(t),
393  priority_tag<2>{}))
394  {
395  return fn::impl(std::forward<T>(t), priority_tag<2>{});
396  }
397  };
398  } // namespace _end
399  namespace {
400  constexpr auto& end = static_const<_end::fn>::value;
401  }
402 
403  // cbegin
404  namespace _cbegin {
405  struct fn {
406  template <typename T>
407  constexpr auto operator()(const T& t) const
408  noexcept(noexcept(::scn::detail::ranges::begin(t)))
409  -> decltype(::scn::detail::ranges::begin(t))
410  {
412  }
413 
414  template <typename T>
415  constexpr auto operator()(const T&& t) const
416  noexcept(noexcept(::scn::detail::ranges::begin(
417  static_cast<const T&&>(t))))
418  -> decltype(::scn::detail::ranges::begin(
419  static_cast<const T&&>(t)))
420  {
422  static_cast<const T&&>(t));
423  }
424  };
425  } // namespace _cbegin
426  namespace {
427  constexpr auto& cbegin = static_const<_cbegin::fn>::value;
428  }
429 
430  // cend
431  namespace _cend {
432  struct fn {
433  template <typename T>
434  constexpr auto operator()(const T& t) const
435  noexcept(noexcept(::scn::detail::ranges::end(t)))
436  -> decltype(::scn::detail::ranges::end(t))
437  {
439  }
440 
441  template <typename T>
442  constexpr auto operator()(const T&& t) const
443  noexcept(noexcept(::scn::detail::ranges::end(
444  static_cast<const T&&>(t))))
445  -> decltype(::scn::detail::ranges::end(
446  static_cast<const T&&>(t)))
447  {
449  static_cast<const T&&>(t));
450  }
451  };
452  } // namespace _cend
453  namespace {
454  constexpr auto& cend = static_const<_cend::fn>::value;
455  }
456 
457  // range
459  template <typename T>
460  auto _test_requires(T&& t) -> decltype(
461  ::scn::detail::ranges::begin(std::forward<T>(t)),
462  ::scn::detail::ranges::end(std::forward<T>(t)));
463  };
464  template <typename T>
465  struct _range_impl : _requires<_range_impl_concept, T> {
466  };
467  struct _range_concept {
468  template <typename>
469  static auto test(long) -> std::false_type;
470  template <typename T>
471  static auto test(int) ->
472  typename std::enable_if<_range_impl<T&>::value,
473  std::true_type>::type;
474  };
475  template <typename T>
476  struct range : decltype(_range_concept::test<T>(0)) {
477  };
478 
479  template <typename T>
481  : std::integral_constant<bool,
482  range<T>::value &&
483  _range_impl<T>::value> {
484  };
485 
486  // typedefs
487  template <typename R>
488  using iterator_t =
489  typename std::enable_if<range<R>::value,
490  decltype(::scn::detail::ranges::begin(
491  std::declval<R&>()))>::type;
492  template <typename R>
493  using sentinel_t =
494  typename std::enable_if<range<R>::value,
495  decltype(::scn::detail::ranges::end(
496  std::declval<R&>()))>::type;
497  template <typename R>
498  using range_difference_t =
499  typename std::enable_if<range<R>::value,
501  template <typename R>
502  using range_value_t =
503  typename std::enable_if<range<R>::value,
505  template <typename R>
506  using range_reference_t =
507  typename std::enable_if<range<R>::value,
509 
510  // view
511  struct view_base {
512  };
513  template <typename>
514  struct _is_std_non_view : std::false_type {
515  };
516  template <typename T>
517  struct _is_std_non_view<std::initializer_list<T>> : std::true_type {
518  };
519  template <typename T>
521  : std::conditional<
522  std::is_base_of<view_base, T>::value,
523  std::true_type,
524  typename std::conditional<
525  _is_std_non_view<T>::value,
526  std::false_type,
527  typename std::conditional<
528  range<T>::value && range<const T>::value,
529  std::is_same<range_reference_t<T>,
530  range_reference_t<const T>>,
531  std::true_type>::type>::type>::type {
532  };
533  template <typename T>
534  struct view
535  : std::integral_constant<
536  bool,
537  range<T>::value && std::is_copy_constructible<T>::value &&
538  std::is_default_constructible<T>::value &&
539  _enable_view_helper<T>::value> {
540  };
541 
542  // data
543  template <typename P>
545  : std::integral_constant<
546  bool,
547  std::is_pointer<P>::value &&
548  std::is_object<_test_t<iter_value_t, P>>::value> {
549  };
550 
551  namespace _data {
552  struct fn {
553  private:
554  template <typename CharT,
555  typename Traits,
556  typename Allocator>
557  static constexpr auto impl(
558  std::basic_string<CharT, Traits, Allocator>& str,
559  priority_tag<2>) noexcept -> typename std::
560  basic_string<CharT, Traits, Allocator>::pointer
561  {
562  return std::addressof(*str.begin());
563  }
564  template <typename CharT,
565  typename Traits,
566  typename Allocator>
567  static constexpr auto impl(
568  const std::basic_string<CharT, Traits, Allocator>& str,
569  priority_tag<2>) noexcept -> typename std::
570  basic_string<CharT, Traits, Allocator>::const_pointer
571  {
572  return std::addressof(*str.begin());
573  }
574  template <typename CharT,
575  typename Traits,
576  typename Allocator>
577  static constexpr auto impl(
578  std::basic_string<CharT, Traits, Allocator>&& str,
579  priority_tag<2>) noexcept -> typename std::
580  basic_string<CharT, Traits, Allocator>::pointer
581  {
582  return std::addressof(*str.begin());
583  }
584 
585  template <typename T,
586  typename D = decltype(
587  decay_copy(std::declval<T&>().data()))>
588  static constexpr auto impl(T& t, priority_tag<1>) noexcept(
589  noexcept(decay_copy(t.data()))) ->
590  typename std::enable_if<_is_object_pointer<D>::value,
591  D>::type
592  {
593  return decay_copy(t.data());
594  }
595 
596  template <typename T>
597  static constexpr auto impl(T&& t, priority_tag<0>) noexcept(
598  noexcept(
599  ::scn::detail::ranges::begin(std::forward<T>(t))))
600  -> typename std::enable_if<
602  decltype(::scn::detail::ranges::begin(
603  std::forward<T>(t)))>::value,
604  decltype(::scn::detail::ranges::begin(
605  std::forward<T>(t)))>::type
606  {
607  return ::scn::detail::ranges::begin(std::forward<T>(t));
608  }
609 
610  public:
611  template <typename T>
612  constexpr auto operator()(T&& t) const
613  noexcept(noexcept(fn::impl(std::forward<T>(t),
614  priority_tag<2>{})))
615  -> decltype(fn::impl(std::forward<T>(t),
616  priority_tag<2>{}))
617  {
618  return fn::impl(std::forward<T>(t), priority_tag<2>{});
619  }
620  };
621  } // namespace _data
622  namespace {
623  constexpr auto& data = static_const<_data::fn>::value;
624  }
625 
626  // size
627  template <typename>
628  struct disable_sized_range : std::false_type {
629  };
630 
631  namespace _size {
632  template <typename T>
633  void size(T&&) = delete;
634  template <typename T>
635  void size(T&) = delete;
636 
637  struct fn {
638  private:
639  template <typename T, std::size_t N>
640  static constexpr std::size_t impl(const T(&&)[N],
641  priority_tag<3>) noexcept
642  {
643  return N;
644  }
645 
646  template <typename T, std::size_t N>
647  static constexpr std::size_t impl(const T (&)[N],
648  priority_tag<3>) noexcept
649  {
650  return N;
651  }
652 
653  template <typename T,
654  typename I = decltype(
655  decay_copy(std::declval<T>().size()))>
656  static constexpr auto impl(T&& t, priority_tag<2>) noexcept(
657  noexcept(decay_copy(std::forward<T>(t).size()))) ->
658  typename std::enable_if<
659  std::is_integral<I>::value &&
661  I>::type
662  {
663  return decay_copy(std::forward<T>(t).size());
664  }
665 
666  template <typename T,
667  typename I =
668  decltype(decay_copy(size(std::declval<T>())))>
669  static constexpr auto impl(T&& t, priority_tag<1>) noexcept(
670  noexcept(decay_copy(size(std::forward<T>(t))))) ->
671  typename std::enable_if<
672  std::is_integral<I>::value &&
674  I>::type
675  {
676  return decay_copy(size(std::forward<T>(t)));
677  }
678 
679  template <
680  typename T,
681  typename I = decltype(
682  ::scn::detail::ranges::begin(std::declval<T>())),
683  typename S = decltype(
684  ::scn::detail::ranges::end(std::declval<T>())),
685  typename D = decltype(decay_copy(std::declval<S>() -
686  std::declval<I>()))>
687  static constexpr auto impl(T&& t, priority_tag<0>) noexcept(
688  noexcept(decay_copy(::scn::detail::ranges::end(t) -
690  -> typename std::enable_if<
691  !std::is_array<remove_cvref_t<T>>::value,
692  D>::type
693  {
696  }
697 
698  public:
699  template <typename T>
700  constexpr auto operator()(T&& t) const
701  noexcept(noexcept(fn::impl(std::forward<T>(t),
702  priority_tag<3>{})))
703  -> decltype(fn::impl(std::forward<T>(t),
704  priority_tag<3>{}))
705  {
706  return fn::impl(std::forward<T>(t), priority_tag<3>{});
707  }
708  };
709  } // namespace _size
710  namespace {
711  constexpr auto& size = static_const<_size::fn>::value;
712  }
713 
714  // empty
715  namespace _empty_ns {
716  struct fn {
717  private:
718  template <typename T>
719  static constexpr auto impl(T&& t, priority_tag<2>) noexcept(
720  noexcept((bool(std::forward<T>(t).empty()))))
721  -> decltype((bool(std::forward<T>(t).empty())))
722  {
723  return bool((std::forward<T>(t).empty()));
724  }
725  template <typename T>
726  static constexpr auto impl(T&& t, priority_tag<1>) noexcept(
727  noexcept(::scn::detail::ranges::size(
728  std::forward<T>(t)) == 0))
729  -> decltype(::scn::detail::ranges::size(
730  std::forward<T>(t)) == 0)
731  {
733  std::forward<T>(t)) == 0;
734  }
735 
736  template <
737  typename T,
738  typename I = decltype(
739  ::scn::detail::ranges::begin(std::declval<T>()))>
740  static constexpr auto impl(T&& t, priority_tag<0>) noexcept(
741  noexcept(::scn::detail::ranges::begin(t) ==
743  -> decltype(::scn::detail::ranges::begin(t) ==
745  {
748  }
749 
750  public:
751  template <typename T>
752  constexpr auto operator()(T&& t) const
753  noexcept(noexcept(fn::impl(std::forward<T>(t),
754  priority_tag<2>{})))
755  -> decltype(fn::impl(std::forward<T>(t),
756  priority_tag<2>{}))
757  {
758  return fn::impl(std::forward<T>(t), priority_tag<2>{});
759  }
760  };
761  } // namespace _empty_ns
762  namespace {
763  constexpr auto& empty = static_const<_empty_ns::fn>::value;
764  }
765 
766  // sized_range
768  template <typename T>
769  auto _test_requires(T& t)
770  -> decltype(::scn::detail::ranges::size(t));
771  };
772  template <typename T>
773  struct sized_range
774  : std::integral_constant<
775  bool,
776  range<T>::value &&
777  !disable_sized_range<
778  detail::remove_cvref_t<T>>::value &&
779  _requires<_sized_range_concept, T>::value> {
780  };
781 
782  // contiguous_range
784  template <typename>
785  static auto test(long) -> std::false_type;
786  template <typename T>
787  static auto test(int) -> typename std::enable_if<
789  std::true_type>::type;
790 
791  template <typename T>
792  auto _test_requires(T& t)
793  -> decltype(requires_expr<std::is_same<
794  decltype(::scn::detail::ranges::data(t)),
795  typename std::add_pointer<
797  };
798  template <typename T>
800  : decltype(_contiguous_range_concept::test<T>(0)) {
801  };
802 
803  // subrange
804  template <typename D>
805  class view_interface : public view_base {
806  static_assert(std::is_class<D>::value, "");
807  static_assert(
808  std::is_same<D, typename std::remove_cv<D>::type>::value,
809  "");
810 
811  private:
812  SCN_CONSTEXPR14 D& derived() noexcept
813  {
814  return static_cast<D&>(*this);
815  }
816  constexpr D& derived() const noexcept
817  {
818  return static_cast<const D&>(*this);
819  }
820 
821  public:
823  {
825  ::scn::detail::ranges::end(derived());
826  }
827  SCN_NODISCARD constexpr bool empty() const
828  {
830  ::scn::detail::ranges::end(derived());
831  }
832 
833  template <typename R = D,
834  typename = decltype(
835  ::scn::detail::ranges::empty(std::declval<R&>()))>
836  SCN_CONSTEXPR14 explicit operator bool()
837  {
838  return !::scn::detail::ranges::empty(derived());
839  }
840  template <typename R = D,
841  typename = decltype(::scn::detail::ranges::empty(
842  std::declval<const R&>()))>
843  constexpr explicit operator bool() const
844  {
845  return !::scn::detail::ranges::empty(derived());
846  }
847 
848  template <typename R = D,
849  typename std::enable_if<
851  auto data() -> decltype(std::addressof(
852  *::scn::detail::ranges::begin(static_cast<R&>(*this))))
853  {
854  return ::scn::detail::ranges::empty(derived())
855  ? nullptr
856  : std::addressof(
857  *::scn::detail::ranges::begin(derived()));
858  }
859  template <typename R = D,
860  typename std::enable_if<contiguous_range<
861  const R>::value>::type* = nullptr>
862  auto data() const
863  -> decltype(std::addressof(*::scn::detail::ranges::begin(
864  static_cast<const R&>(*this))))
865  {
866  return ::scn::detail::ranges::empty(derived())
867  ? nullptr
868  : std::addressof(
869  *::scn::detail::ranges::begin(derived()));
870  }
871 
872  template <typename R = D,
873  typename std::enable_if<
874  range<R>::value &&
876  value>::type* = nullptr>
877  SCN_CONSTEXPR14 auto size() -> decltype(
878  ::scn::detail::ranges::end(static_cast<R&>(*this)) -
879  ::scn::detail::ranges::begin(static_cast<R&>(*this)))
880  {
882  ::scn::detail::ranges::begin(derived());
883  }
884 
885  template <
886  typename R = D,
887  typename std::enable_if<
891  nullptr>
892  constexpr auto size() const -> decltype(
893  ::scn::detail::ranges::end(static_cast<const R&>(*this)) -
894  ::scn::detail::ranges::begin(static_cast<const R&>(*this)))
895  {
897  ::scn::detail::ranges::begin(derived());
898  }
899  };
900 
901  enum class subrange_kind : bool { unsized, sized };
902 
903  template <typename I, typename S>
905  : std::integral_constant<subrange_kind,
906  sized_sentinel_for<S, I>::value
907  ? subrange_kind::sized
908  : subrange_kind::unsized> {
909  };
910 
911  namespace _subrange {
912  template <typename I,
913  typename S = I,
915  class subrange;
916  } // namespace _subrange
917 
918  using _subrange::subrange;
919 
921  template <typename>
922  static auto test(long) -> std::false_type;
923  template <typename T,
924  typename = typename std::tuple_size<T>::type>
925  static auto test(int) -> typename std::enable_if<
927  std::true_type>::type;
928 
929  template <typename T>
930  auto _test_requires(T t) -> decltype(
932  std::is_base_of<std::integral_constant<std::size_t, 2>,
933  std::tuple_size<T>>::value>{},
934  std::declval<std::tuple_element<
935  0,
936  typename std::remove_const<T>::type>>(),
937  std::declval<std::tuple_element<
938  1,
939  typename std::remove_const<T>::type>>(),
940  requires_expr<std::is_convertible<
941  decltype(std::get<0>(t)),
942  const std::tuple_element<0, T>&>::value>{},
943  requires_expr<std::is_convertible<
944  decltype(std::get<1>(t)),
945  const std::tuple_element<1, T>&>::value>{});
946  };
947  template <typename T>
948  struct _pair_like
949  : std::integral_constant<
950  bool,
951  !std::is_reference<T>::value &&
952  decltype(_pair_like_concept::test<T>(0))::value> {
953  };
954 
956  template <typename T, typename U, typename V>
957  auto _test_requires(T&& t)
958  -> decltype(requires_expr<std::is_convertible<
959  decltype(std::get<0>(std::forward<T>(t))),
960  U>::value>{},
961  requires_expr<std::is_convertible<
962  decltype(std::get<1>(std::forward<T>(t))),
963  V>::value>{});
964  };
965  template <typename T, typename U, typename V>
967  : std::integral_constant<
968  bool,
969  !range<T>::value &&
970  _pair_like<
971  typename std::remove_reference<T>::type>::value &&
972  _requires<_pair_like_convertible_to_concept,
973  T,
974  U,
975  V>::value> {
976  };
977  template <typename T, typename U, typename V>
979  : std::integral_constant<
980  bool,
981  !range<T>::value &&
982  _pair_like<
983  typename std::remove_reference<T>::type>::value &&
984  std::is_constructible<T, U, V>::value> {
985  };
986 
988  template <typename>
989  static auto test(long) -> std::false_type;
990  template <typename T>
991  static auto test(int) -> typename std::enable_if<
993  sentinel_for<
996  std::true_type>::type;
997  };
998  template <typename T>
1000  : decltype(_iterator_sentinel_pair_concept::test<T>(0)) {
1001  };
1002 
1003  template <typename I, typename S, bool StoreSize = false>
1005  constexpr _subrange_data() = default;
1006  constexpr _subrange_data(I&& b, S&& e)
1007  : begin(std::move(b)), end(std::move(e))
1008  {
1009  }
1010  template <bool Dependent = true>
1011  constexpr _subrange_data(
1012  I&& b,
1013  S&& e,
1014  typename std::enable_if<Dependent,
1016  : begin(std::move(b)), end(std::move(e))
1017  {
1018  }
1019 
1020  constexpr iter_difference_t<I> get_size() const
1021  {
1022  return distance(begin, end);
1023  }
1024 
1025  I begin{};
1026  S end{};
1027  };
1028 
1029  template <typename I, typename S>
1030  struct _subrange_data<I, S, true> {
1031  constexpr _subrange_data() = default;
1032  constexpr _subrange_data(I&& b, S&& e, iter_difference_t<I> s)
1033  : begin(std::move(b)), end(std::move(e)), size(s)
1034  {
1035  }
1036 
1037  constexpr iter_difference_t<I> get_size() const
1038  {
1039  return size;
1040  }
1041 
1042  I begin{};
1043  S end{};
1045  };
1046 
1047  template <typename R, typename I, typename S, subrange_kind K>
1049  -> std::false_type;
1050 
1051  template <typename R, typename I, typename S, subrange_kind K>
1053  typename std::enable_if<
1054  forwarding_range<R>::value &&
1055  std::is_convertible<iterator_t<R>, I>::value &&
1056  std::is_convertible<sentinel_t<R>, S>::value,
1057  std::true_type>::type;
1058 
1059  template <typename R, typename I, typename S, subrange_kind K>
1061  : decltype(
1062  _subrange_range_constructor_constraint_helper_fn<R,
1063  I,
1064  S,
1065  K>(0)) {
1066  };
1067 
1068  template <typename R>
1070  {
1071  return (sized_range<R>::value ||
1075  }
1076 
1077  template <typename T, typename U>
1078  struct _not_same_as : std::integral_constant<
1079  bool,
1080  !std::is_same<remove_cvref_t<T>,
1081  remove_cvref_t<U>>::value> {
1082  };
1083 
1084  namespace _subrange {
1085  template <typename I, typename S, subrange_kind K>
1086  class subrange : public view_interface<subrange<I, S, K>> {
1087  static_assert(sentinel_for<S, I>::value, "");
1088  static_assert(K == subrange_kind::sized ||
1090  "");
1091 
1092  static constexpr bool _store_size =
1093  K == subrange_kind::sized &&
1095 
1096  public:
1097  using iterator = I;
1098  using sentinel = S;
1099 
1100  subrange() = default;
1101 
1102  template <bool SS = _store_size,
1103  typename std::enable_if<!SS>::type* = nullptr>
1105  : m_data{std::move(i), std::move(s)}
1106  {
1107  }
1108  template <bool Dependent = true,
1109  subrange_kind KK = K,
1110  typename std::enable_if<
1111  KK == subrange_kind::sized>::type* = nullptr>
1113  I i,
1114  S s,
1115  typename std::enable_if<Dependent,
1117  : m_data{std::move(i), std::move(s), n}
1118  {
1119  }
1120 
1121  constexpr I begin() const noexcept
1122  {
1123  return m_data.begin;
1124  }
1125 
1126  constexpr S end() const noexcept
1127  {
1128  return m_data.end;
1129  }
1130 
1131  SCN_NODISCARD constexpr bool empty() const noexcept
1132  {
1133  return m_data.begin == m_data.end;
1134  }
1135 
1136  template <subrange_kind KK = K,
1137  typename std::enable_if<
1138  KK == subrange_kind::sized>::type* = nullptr>
1139  constexpr iter_difference_t<I> size() const noexcept
1140  {
1141  return m_data.get_size();
1142  }
1143 
1144  private:
1146  };
1147 
1148  template <typename I, typename S, subrange_kind K>
1149  I begin(subrange<I, S, K>&& r) noexcept
1150  {
1151  return r.begin();
1152  }
1153  template <typename I, typename S, subrange_kind K>
1154  S end(subrange<I, S, K>&& r) noexcept
1155  {
1156  return r.end();
1157  }
1158  } // namespace _subrange
1159 
1160  template <std::size_t N>
1162  template <>
1164  template <typename I, typename S, subrange_kind K>
1165  static auto get(const subrange<I, S, K>& s)
1166  -> decltype(s.begin())
1167  {
1168  return s.begin();
1169  }
1170  };
1171  template <>
1173  template <typename I, typename S, subrange_kind K>
1174  static auto get(const subrange<I, S, K>& s) -> decltype(s.end())
1175  {
1176  return s.end();
1177  }
1178  };
1179 
1180  template <std::size_t N,
1181  typename I,
1182  typename S,
1183  subrange_kind K,
1184  typename std::enable_if<(N < 2)>::type* = nullptr>
1185  auto get(const subrange<I, S, K>& s)
1186  -> decltype(_subrange_get_impl<N>::get(s))
1187  {
1188  return _subrange_get_impl<N>::get(s);
1189  }
1190 
1191  // reconstructible_range
1192  template <typename R>
1194  : std::integral_constant<
1195  bool,
1196  range<R>::value &&
1197  forwarding_range<
1198  typename std::remove_reference<R>::type>::value &&
1199  std::is_constructible<R,
1200  iterator_t<R>,
1201  sentinel_t<R>>::value> {
1202  };
1203  template <typename R>
1205  : std::integral_constant<
1206  bool,
1207  range<R>::value &&
1208  forwarding_range<
1209  typename std::remove_reference<R>::type>::value &&
1210  std::is_constructible<
1211  R,
1212  subrange<iterator_t<R>, sentinel_t<R>>>::value> {
1213  };
1214 
1215  // bidir iterator
1217  template <typename I>
1218  auto _test_requires(I i) -> decltype(
1219  requires_expr<std::is_same<decltype(i--), I>::value>{});
1220  template <typename>
1221  static auto test(long) -> std::false_type;
1222  template <typename I>
1223  static auto test(int) -> typename std::enable_if<
1224  std::is_base_of<bidirectional_iterator_tag,
1227  std::true_type>::type;
1228  };
1229  template <typename I>
1231  : decltype(_bidirectional_iterator_concept::test<I>(0)) {
1232  };
1233 
1234  // random access iterator
1236  template <typename I>
1237  auto _test_requires(I i,
1238  const I j,
1239  const iter_difference_t<I> n)
1240  -> decltype(valid_expr(
1241  j + n,
1242  requires_expr<
1243  std::is_same<decltype(j + n), I>::value>{},
1244  n + j,
1245 #ifndef _MSC_VER
1246  requires_expr<
1247  std::is_same<decltype(n + j), I>::value>{},
1248 #endif
1249  j - n,
1250  requires_expr<
1251  std::is_same<decltype(j - n), I>::value>{},
1252  j[n],
1253  requires_expr<
1254  std::is_same<decltype(j[n]),
1256  requires_expr<std::is_convertible<decltype(i < j),
1257  bool>::value>{}));
1258  template <typename>
1259  static auto test(long) -> std::false_type;
1260  template <typename I>
1261  static auto test(int) -> typename std::enable_if<
1262  bidirectional_iterator<I>::value &&
1263  std::is_base_of<random_access_iterator_tag,
1264  iterator_category_t<I>>::value &&
1265  sized_sentinel_for<I, I>::value &&
1266  _requires<_random_access_iterator_concept, I>::value,
1267  std::true_type>::type;
1268  };
1269  template <typename I>
1271  : decltype(_random_access_iterator_concept::test<I>(0)) {
1272  };
1273 
1274  // advance
1275  namespace _advance {
1276  struct fn {
1277  private:
1278  template <typename T>
1279  static constexpr T abs(T t)
1280  {
1281  return t < T{0} ? -t : t;
1282  }
1283 
1284  template <typename R,
1285  typename std::enable_if<random_access_iterator<
1286  R>::value>::type* = nullptr>
1287  static SCN_CONSTEXPR14 void impl(R& r,
1289  {
1290  r += n;
1291  }
1292 
1293  template <
1294  typename I,
1295  typename std::enable_if<
1298  static SCN_CONSTEXPR14 void impl(I& i,
1300  {
1301  constexpr auto zero = iter_difference_t<I>{0};
1302 
1303  if (n > zero) {
1304  while (n-- > zero) {
1305  ++i;
1306  }
1307  }
1308  else {
1309  while (n++ < zero) {
1310  --i;
1311  }
1312  }
1313  }
1314 
1315  template <typename I,
1316  typename std::enable_if<!bidirectional_iterator<
1317  I>::value>::type* = nullptr>
1318  static SCN_CONSTEXPR14 void impl(I& i,
1320  {
1321  while (n-- > iter_difference_t<I>{0}) {
1322  ++i;
1323  }
1324  }
1325 
1326  template <
1327  typename I,
1328  typename S,
1329  typename std::enable_if<
1330  std::is_assignable<I&, S>::value>::type* = nullptr>
1331  static SCN_CONSTEXPR14 void impl(I& i,
1332  S bound,
1334  {
1335  i = std::move(bound);
1336  }
1337 
1338  template <
1339  typename I,
1340  typename S,
1341  typename std::enable_if<
1343  static SCN_CONSTEXPR14 void impl(I& i,
1344  S bound,
1346  {
1347  fn::impl(i, bound - i);
1348  }
1349 
1350  template <typename I, typename S>
1351  static SCN_CONSTEXPR14 void impl(I& i,
1352  S bound,
1354  {
1355  while (i != bound) {
1356  ++i;
1357  }
1358  }
1359 
1360  template <
1361  typename I,
1362  typename S,
1363  typename std::enable_if<
1365  static SCN_CONSTEXPR14 auto impl(I& i,
1367  S bound)
1369  {
1370  if (fn::abs(n) >= fn::abs(bound - i)) {
1371  auto dist = bound - i;
1372  fn::impl(i, bound, priority_tag<2>{});
1373  return dist;
1374  }
1375  else {
1376  fn::impl(i, n);
1377  return n;
1378  }
1379  }
1380 
1381  template <
1382  typename I,
1383  typename S,
1384  typename std::enable_if<
1387  static SCN_CONSTEXPR14 auto impl(I& i,
1389  S bound)
1391  {
1392  constexpr iter_difference_t<I> zero{0};
1393  iter_difference_t<I> counter{0};
1394 
1395  if (n < zero) {
1396  do {
1397  --i;
1398  --counter;
1399  } while (++n < zero && i != bound);
1400  }
1401  else {
1402  while (n-- > zero && i != bound) {
1403  ++i;
1404  ++counter;
1405  }
1406  }
1407 
1408  return counter;
1409  }
1410 
1411  template <
1412  typename I,
1413  typename S,
1414  typename std::enable_if<
1417  static SCN_CONSTEXPR14 auto impl(I& i,
1419  S bound)
1421  {
1422  constexpr iter_difference_t<I> zero{0};
1423  iter_difference_t<I> counter{0};
1424 
1425  while (n-- > zero && i != bound) {
1426  ++i;
1427  ++counter;
1428  }
1429 
1430  return counter;
1431  }
1432 
1433  public:
1434  template <typename I>
1436  I& i,
1437  iter_difference_t<I> n) const
1438  {
1439  fn::impl(i, n);
1440  }
1441 
1442  template <typename I,
1443  typename S,
1444  typename std::enable_if<
1445  sentinel_for<S, I>::value>::type* = nullptr>
1446  SCN_CONSTEXPR14 void operator()(I& i, S bound) const
1447  {
1448  fn::impl(i, bound, priority_tag<2>{});
1449  }
1450 
1451  template <typename I,
1452  typename S,
1453  typename std::enable_if<
1454  sentinel_for<S, I>::value>::type* = nullptr>
1456  operator()(I& i, iter_difference_t<I> n, S bound) const
1457  {
1458  return n - fn::impl(i, n, bound);
1459  }
1460  };
1461  } // namespace _advance
1462  namespace {
1463  constexpr auto& advance = static_const<_advance::fn>::value;
1464  }
1465 
1466  // distance
1467  namespace _distance {
1468  struct fn {
1469  private:
1470  template <typename I, typename S>
1471  static SCN_CONSTEXPR14 auto impl(I i, S s) ->
1472  typename std::enable_if<sized_sentinel_for<S, I>::value,
1474  {
1475  return s - i;
1476  }
1477 
1478  template <typename I, typename S>
1479  static SCN_CONSTEXPR14 auto impl(I i, S s) ->
1480  typename std::enable_if<
1483  {
1484  iter_difference_t<I> counter{0};
1485  while (i != s) {
1486  ++i;
1487  ++counter;
1488  }
1489  return counter;
1490  }
1491 
1492  template <typename R>
1493  static SCN_CONSTEXPR14 auto impl(R&& r) ->
1494  typename std::enable_if<
1497  {
1498  return static_cast<iter_difference_t<iterator_t<R>>>(
1499  ranges::size(r));
1500  }
1501 
1502  template <typename R>
1503  static SCN_CONSTEXPR14 auto impl(R&& r) ->
1504  typename std::enable_if<
1507  {
1508  return fn::impl(ranges::begin(r), ranges::end(r));
1509  }
1510 
1511  public:
1512  template <typename I, typename S>
1513  SCN_CONSTEXPR14 auto operator()(I first, S last) const ->
1514  typename std::enable_if<sentinel_for<S, I>::value,
1516  {
1517  return fn::impl(std::move(first), std::move(last));
1518  }
1519 
1520  template <typename R>
1521  SCN_CONSTEXPR14 auto operator()(R&& r) const ->
1522  typename std::enable_if<
1523  range<R>::value,
1525  {
1526  return fn::impl(std::forward<R>(r));
1527  }
1528  };
1529  } // namespace _distance
1530  namespace {
1531  constexpr auto& distance = static_const<_distance::fn>::value;
1532  }
1533  } // namespace ranges
1534  } // namespace detail
1535 
1537 } // namespace scn
1538 
1539 namespace std {
1540  template <typename I, typename S, ::scn::detail::ranges::subrange_kind K>
1541  class tuple_size<::scn::detail::ranges::subrange<I, S, K>>
1542  : public integral_constant<size_t, 2> {
1543  };
1544 
1545  template <typename I, typename S, ::scn::detail::ranges::subrange_kind K>
1546  class tuple_element<0, ::scn::detail::ranges::subrange<I, S, K>> {
1547  public:
1548  using type = I;
1549  };
1550  template <typename I, typename S, ::scn::detail::ranges::subrange_kind K>
1551  class tuple_element<1, ::scn::detail::ranges::subrange<I, S, K>> {
1552  public:
1553  using type = S;
1554  };
1555 
1557 } // namespace std
1558 
1559 #endif // SCN_DETAIL_RANGES_H
auto _test_requires(T &t) -> decltype(requires_expr< std::is_same< decltype(::scn::detail::ranges::data(t)), typename std::add_pointer< range_reference_t< T >>::type >::value >
Definition: ranges.h:792
static auto test(long) -> std::false_type
constexpr const_iterator begin() const noexcept
Definition: string_view.h:103
constexpr auto operator()(const T &t) const noexcept(noexcept(::scn::detail::ranges::end(t))) -> decltype(::scn::detail::ranges::end(t))
Definition: ranges.h:434
typename make_void< Ts...>::type void_t
Definition: util.h:38
std::make_signed< decltype(std::declval< T >()-std::declval< T >())>::type difference_type
Definition: ranges.h:76
auto data() -> decltype(std::addressof(*::scn::detail::ranges::begin(static_cast< R & >(*this))))
Definition: ranges.h:851
static auto test(long) -> std::false_type
constexpr auto operator()(T &&t) const noexcept(noexcept(fn::impl(std::forward< T >(t), priority_tag< 2 >{}))) -> decltype(fn::impl(std::forward< T >(t), priority_tag< 2 >
Definition: ranges.h:612
#define SCN_END_NAMESPACE
Definition: config.h:406
void size(T &&)=delete
static auto test(long) -> std::false_type
typename std::enable_if< range< R >::value, iter_reference_t< iterator_t< R >>>::type range_reference_t
Definition: ranges.h:508
auto _test_requires(T &t) -> decltype(::scn::detail::ranges::size(t))
decltype(*std::declval< T & >()) iter_reference_t
Definition: ranges.h:65
SCN_CONSTEXPR14 void operator()(I &i, S bound) const
Definition: ranges.h:1446
typename std::enable_if< Expr, int >::type requires_expr
Definition: util.h:124
SCN_NODISCARD constexpr bool empty() const
Definition: ranges.h:827
I begin(subrange< I, S, K > &&r) noexcept
Definition: ranges.h:1149
SCN_CONSTEXPR14 auto operator()(R &&r) const -> typename std::enable_if< range< R >::value, iter_difference_t< iterator_t< R >>>::type
Definition: ranges.h:1521
typename std::enable_if< range< R >::value, decltype(::scn::detail::ranges::end(std::declval< R & >()))>::type sentinel_t
Definition: ranges.h:496
SCN_CONSTEXPR14 subrange(I i, S s)
Definition: ranges.h:1104
constexpr subrange_kind _subrange_deduction_guide_helper()
Definition: ranges.h:1069
constexpr _subrange_data()=default
SCN_CONSTEXPR14 auto operator()(T &&t) const noexcept(noexcept(fn::impl(std::forward< T >(t), priority_tag< 3 >{}))) -> decltype(fn::impl(std::forward< T >(t), priority_tag< 3 >
Definition: ranges.h:319
static auto test(long) -> std::false_type
typename T::element_type _member_element_type_t
Definition: ranges.h:189
typename T::value_type _member_value_type_t
Definition: ranges.h:182
constexpr iter_difference_t< I > get_size() const
Definition: ranges.h:1020
constexpr auto operator()(T &&t) const noexcept(noexcept(fn::impl(std::forward< T >(t), priority_tag< 3 >{}))) -> decltype(fn::impl(std::forward< T >(t), priority_tag< 3 >
Definition: ranges.h:700
auto _subrange_range_constructor_constraint_helper_fn(long) -> std::false_type
typename readable_traits< T >::value_type iter_value_t
Definition: ranges.h:227
typename std::enable_if< range< R >::value, decltype(::scn::detail::ranges::begin(std::declval< R & >()))>::type iterator_t
Definition: ranges.h:491
SCN_CONSTEXPR14 subrange(I i, S s, typename std::enable_if< Dependent, iter_difference_t< I >>::type n)
Definition: ranges.h:1112
constexpr iter_difference_t< I > get_size() const
Definition: ranges.h:1037
constexpr const_iterator end() const noexcept
Definition: string_view.h:111
auto _test_requires(T &&t) -> decltype(requires_expr< std::is_convertible< decltype(std::get< 0 >(std::forward< T >(t))), U >::value >
Definition: ranges.h:957
S end(subrange< I, S, K > &&r) noexcept
Definition: ranges.h:1154
auto _test_requires(I i) -> decltype(requires_expr< std::is_same< decltype(i--), I >::value >
Definition: ranges.h:1218
auto _test_requires(I i, const I j, const iter_difference_t< I > n) -> decltype(valid_expr(j+n, requires_expr< std::is_same< decltype(j+n), I >::value >
Definition: ranges.h:1237
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
constexpr _subrange_data(I &&b, S &&e, typename std::enable_if< Dependent, iter_difference_t< I >>::type)
Definition: ranges.h:1011
auto data() const -> decltype(std::addressof(*::scn::detail::ranges::begin(static_cast< const R & >(*this))))
Definition: ranges.h:862
SCN_CONSTEXPR14 auto size() -> decltype(::scn::detail::ranges::end(static_cast< R & >(*this))-::scn::detail::ranges::begin(static_cast< R & >(*this)))
Definition: ranges.h:877
#define SCN_NODISCARD
Definition: config.h:270
auto _test_requires(S s, I i) -> decltype(scn::detail::valid_expr(*i, i==s, i!=s))
static auto test(long) -> std::false_type
constexpr _subrange_data(I &&b, S &&e, iter_difference_t< I > s)
Definition: ranges.h:1032
typename std::enable_if< range< R >::value, iter_difference_t< iterator_t< R >>>::type range_difference_t
Definition: ranges.h:500
SCN_CONSTEXPR14 iter_difference_t< I > operator()(I &i, iter_difference_t< I > n, S bound) const
Definition: ranges.h:1456
#define SCN_BEGIN_NAMESPACE
Definition: config.h:405
SCN_CONSTEXPR14 auto operator()(I first, S last) const -> typename std::enable_if< sentinel_for< S, I >::value, iter_difference_t< I >>::type
Definition: ranges.h:1513
SCN_NODISCARD constexpr bool empty() const noexcept
Definition: ranges.h:1131
typename std::enable_if< range< R >::value, iter_value_t< iterator_t< R >>>::type range_value_t
Definition: ranges.h:504
auto _test_requires(T t) -> decltype(requires_expr< std::is_base_of< std::integral_constant< std::size_t, 2 >, std::tuple_size< T >>::value >
Definition: ranges.h:930
constexpr auto operator()(const T &&t) const noexcept(noexcept(::scn::detail::ranges::begin(static_cast< const T && >(t)))) -> decltype(::scn::detail::ranges::begin(static_cast< const T && >(t)))
Definition: ranges.h:415
static auto test(long) -> std::false_type
typename incrementable_traits< T >::difference_type iter_difference_t
Definition: ranges.h:130
typename iterator_category< T >::type iterator_category_t
Definition: ranges.h:62
SCN_NODISCARD SCN_CONSTEXPR14 bool empty()
Definition: ranges.h:822
void end(T &&)=delete
constexpr auto operator()(T &&t) const noexcept(noexcept(fn::impl(std::forward< T >(t), priority_tag< 2 >{}))) -> decltype(fn::impl(std::forward< T >(t), priority_tag< 2 >
Definition: ranges.h:752
constexpr I begin() const noexcept
Definition: ranges.h:1121
void valid_expr(T &&...)
void begin(T &&)=delete
constexpr S end() const noexcept
Definition: ranges.h:1126
constexpr auto size() const -> decltype(::scn::detail::ranges::end(static_cast< const R & >(*this))-::scn::detail::ranges::begin(static_cast< const R & >(*this)))
Definition: ranges.h:892
constexpr auto operator()(const T &t) const noexcept(noexcept(::scn::detail::ranges::begin(t))) -> decltype(::scn::detail::ranges::begin(t))
Definition: ranges.h:407
SCN_CONSTEXPR14 void operator()(I &i, iter_difference_t< I > n) const
Definition: ranges.h:1435
A view over a (sub)string.
Definition: string_view.h:60
auto _test_requires(const S &s, const I &i) -> decltype(requires_expr< std::is_same< decltype(s-i), iter_difference_t< I >>::value >
Definition: ranges.h:247
auto get(const subrange< I, S, K > &s) -> decltype(_subrange_get_impl< N >::get(s))
Definition: ranges.h:1185
auto _test_requires(T &&t) -> decltype(::scn::detail::ranges::begin(std::forward< T >(t)),::scn::detail::ranges::end(std::forward< T >(t)))
constexpr auto operator()(const T &&t) const noexcept(noexcept(::scn::detail::ranges::end(static_cast< const T && >(t)))) -> decltype(::scn::detail::ranges::end(static_cast< const T && >(t)))
Definition: ranges.h:442
constexpr iter_difference_t< I > size() const noexcept
Definition: ranges.h:1139
constexpr auto operator()(T &&t) const noexcept(noexcept(fn::impl(std::forward< T >(t), priority_tag< 2 >{}))) -> decltype(fn::impl(std::forward< T >(t), priority_tag< 2 >
Definition: ranges.h:389
constexpr _subrange_data(I &&b, S &&e)
Definition: ranges.h:1006
#define SCN_CONSTEXPR14
Definition: config.h:246