Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f51ee63

Browse files
committed
Make next/prev/advance/distance operations on iterators be constexpr. I missed this when I implemented the rest of P0031R0
llvm-svn: 303281
1 parent d38107b commit f51ee63

6 files changed

Lines changed: 203 additions & 81 deletions

File tree

libcxx/include/iterator

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,23 @@ struct forward_iterator_tag : public input_iterator_tag {};
6464
struct bidirectional_iterator_tag : public forward_iterator_tag {};
6565
struct random_access_iterator_tag : public bidirectional_iterator_tag {};
6666
67+
// 27.4.3, iterator operations
6768
// extension: second argument not conforming to C++03
68-
template <class InputIterator>
69-
void advance(InputIterator& i,
69+
template <class InputIterator> // constexpr in C++17
70+
constexpr void advance(InputIterator& i,
7071
typename iterator_traits<InputIterator>::difference_type n);
7172
72-
template <class InputIterator>
73-
typename iterator_traits<InputIterator>::difference_type
74-
distance(InputIterator first, InputIterator last);
73+
template <class InputIterator> // constexpr in C++17
74+
constexpr typename iterator_traits<InputIterator>::difference_type
75+
distance(InputIterator first, InputIterator last);
76+
77+
template <class InputIterator> // constexpr in C++17
78+
constexpr InputIterator next(InputIterator x,
79+
typename iterator_traits<InputIterator>::difference_type n = 1);
80+
81+
template <class BidirectionalIterator> // constexpr in C++17
82+
constexpr BidirectionalIterator prev(BidirectionalIterator x,
83+
typename iterator_traits<BidirectionalIterator>::difference_type n = 1);
7584
7685
template <class Iterator>
7786
class reverse_iterator
@@ -529,7 +538,7 @@ struct _LIBCPP_TEMPLATE_VIS iterator
529538
};
530539

531540
template <class _InputIter>
532-
inline _LIBCPP_INLINE_VISIBILITY
541+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
533542
void __advance(_InputIter& __i,
534543
typename iterator_traits<_InputIter>::difference_type __n, input_iterator_tag)
535544
{
@@ -538,7 +547,7 @@ void __advance(_InputIter& __i,
538547
}
539548

540549
template <class _BiDirIter>
541-
inline _LIBCPP_INLINE_VISIBILITY
550+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
542551
void __advance(_BiDirIter& __i,
543552
typename iterator_traits<_BiDirIter>::difference_type __n, bidirectional_iterator_tag)
544553
{
@@ -551,23 +560,23 @@ void __advance(_BiDirIter& __i,
551560
}
552561

553562
template <class _RandIter>
554-
inline _LIBCPP_INLINE_VISIBILITY
563+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
555564
void __advance(_RandIter& __i,
556565
typename iterator_traits<_RandIter>::difference_type __n, random_access_iterator_tag)
557566
{
558567
__i += __n;
559568
}
560569

561570
template <class _InputIter>
562-
inline _LIBCPP_INLINE_VISIBILITY
571+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
563572
void advance(_InputIter& __i,
564573
typename iterator_traits<_InputIter>::difference_type __n)
565574
{
566575
__advance(__i, __n, typename iterator_traits<_InputIter>::iterator_category());
567576
}
568577

569578
template <class _InputIter>
570-
inline _LIBCPP_INLINE_VISIBILITY
579+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
571580
typename iterator_traits<_InputIter>::difference_type
572581
__distance(_InputIter __first, _InputIter __last, input_iterator_tag)
573582
{
@@ -578,23 +587,23 @@ __distance(_InputIter __first, _InputIter __last, input_iterator_tag)
578587
}
579588

580589
template <class _RandIter>
581-
inline _LIBCPP_INLINE_VISIBILITY
590+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
582591
typename iterator_traits<_RandIter>::difference_type
583592
__distance(_RandIter __first, _RandIter __last, random_access_iterator_tag)
584593
{
585594
return __last - __first;
586595
}
587596

588597
template <class _InputIter>
589-
inline _LIBCPP_INLINE_VISIBILITY
598+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
590599
typename iterator_traits<_InputIter>::difference_type
591600
distance(_InputIter __first, _InputIter __last)
592601
{
593602
return __distance(__first, __last, typename iterator_traits<_InputIter>::iterator_category());
594603
}
595604

596605
template <class _InputIter>
597-
inline _LIBCPP_INLINE_VISIBILITY
606+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
598607
_InputIter
599608
next(_InputIter __x,
600609
typename iterator_traits<_InputIter>::difference_type __n = 1,
@@ -605,7 +614,7 @@ next(_InputIter __x,
605614
}
606615

607616
template <class _BidiretionalIter>
608-
inline _LIBCPP_INLINE_VISIBILITY
617+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
609618
_BidiretionalIter
610619
prev(_BidiretionalIter __x,
611620
typename iterator_traits<_BidiretionalIter>::difference_type __n = 1,

libcxx/test/std/iterators/iterator.primitives/iterator.operations/advance.pass.cpp

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,16 @@
99

1010
// <iterator>
1111

12+
// All of these became constexpr in C++17
13+
//
1214
// template <InputIterator Iter>
13-
// void advance(Iter& i, Iter::difference_type n);
15+
// constexpr void advance(Iter& i, Iter::difference_type n);
1416
//
1517
// template <BidirectionalIterator Iter>
16-
// void advance(Iter& i, Iter::difference_type n);
18+
// constexpr void advance(Iter& i, Iter::difference_type n);
1719
//
1820
// template <RandomAccessIterator Iter>
19-
// void advance(Iter& i, Iter::difference_type n);
21+
// constexpr void advance(Iter& i, Iter::difference_type n);
2022

2123
#include <iterator>
2224
#include <cassert>
@@ -31,8 +33,19 @@ test(It i, typename std::iterator_traits<It>::difference_type n, It x)
3133
assert(i == x);
3234
}
3335

36+
#if TEST_STD_VER > 14
37+
template <class It>
38+
constexpr bool
39+
constepxr_test(It i, typename std::iterator_traits<It>::difference_type n, It x)
40+
{
41+
std::advance(i, n);
42+
return i == x;
43+
}
44+
#endif
45+
3446
int main()
3547
{
48+
{
3649
const char* s = "1234567890";
3750
test(input_iterator<const char*>(s), 10, input_iterator<const char*>(s+10));
3851
test(forward_iterator<const char*>(s), 10, forward_iterator<const char*>(s+10));
@@ -42,4 +55,18 @@ int main()
4255
test(random_access_iterator<const char*>(s+5), -5, random_access_iterator<const char*>(s));
4356
test(s+5, 5, s+10);
4457
test(s+5, -5, s);
58+
}
59+
#if TEST_STD_VER > 14
60+
{
61+
constexpr const char* s = "1234567890";
62+
static_assert( constepxr_test(input_iterator<const char*>(s), 10, input_iterator<const char*>(s+10)), "" );
63+
static_assert( constepxr_test(forward_iterator<const char*>(s), 10, forward_iterator<const char*>(s+10)), "" );
64+
static_assert( constepxr_test(bidirectional_iterator<const char*>(s+5), 5, bidirectional_iterator<const char*>(s+10)), "" );
65+
static_assert( constepxr_test(bidirectional_iterator<const char*>(s+5), -5, bidirectional_iterator<const char*>(s)), "" );
66+
static_assert( constepxr_test(random_access_iterator<const char*>(s+5), 5, random_access_iterator<const char*>(s+10)), "" );
67+
static_assert( constepxr_test(random_access_iterator<const char*>(s+5), -5, random_access_iterator<const char*>(s)), "" );
68+
static_assert( constepxr_test(s+5, 5, s+10), "" );
69+
static_assert( constepxr_test(s+5, -5, s), "" );
70+
}
71+
#endif
4572
}

libcxx/test/std/iterators/iterator.primitives/iterator.operations/distance.pass.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,33 @@ test(It first, It last, typename std::iterator_traits<It>::difference_type x)
2929
assert(std::distance(first, last) == x);
3030
}
3131

32+
#if TEST_STD_VER > 14
33+
template <class It>
34+
constexpr bool
35+
constexpr_test(It first, It last, typename std::iterator_traits<It>::difference_type x)
36+
{
37+
return std::distance(first, last) == x;
38+
}
39+
#endif
40+
3241
int main()
3342
{
43+
{
3444
const char* s = "1234567890";
3545
test(input_iterator<const char*>(s), input_iterator<const char*>(s+10), 10);
3646
test(forward_iterator<const char*>(s), forward_iterator<const char*>(s+10), 10);
3747
test(bidirectional_iterator<const char*>(s), bidirectional_iterator<const char*>(s+10), 10);
3848
test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s+10), 10);
3949
test(s, s+10, 10);
50+
}
51+
#if TEST_STD_VER > 14
52+
{
53+
constexpr const char* s = "1234567890";
54+
static_assert( constexpr_test(input_iterator<const char*>(s), input_iterator<const char*>(s+10), 10), "");
55+
static_assert( constexpr_test(forward_iterator<const char*>(s), forward_iterator<const char*>(s+10), 10), "");
56+
static_assert( constexpr_test(bidirectional_iterator<const char*>(s), bidirectional_iterator<const char*>(s+10), 10), "");
57+
static_assert( constexpr_test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s+10), 10), "");
58+
static_assert( constexpr_test(s, s+10, 10), "");
59+
}
60+
#endif
4061
}

libcxx/test/std/iterators/iterator.primitives/iterator.operations/next.pass.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,25 @@ test(It i, It x)
3333
assert(std::next(i) == x);
3434
}
3535

36+
#if TEST_STD_VER > 14
37+
template <class It>
38+
constexpr bool
39+
constexpr_test(It i, typename std::iterator_traits<It>::difference_type n, It x)
40+
{
41+
return std::next(i, n) == x;
42+
}
43+
44+
template <class It>
45+
constexpr bool
46+
constexpr_test(It i, It x)
47+
{
48+
return std::next(i) == x;
49+
}
50+
#endif
51+
3652
int main()
3753
{
54+
{
3855
const char* s = "1234567890";
3956
test(input_iterator<const char*>(s), 10, input_iterator<const char*>(s+10));
4057
test(forward_iterator<const char*>(s), 10, forward_iterator<const char*>(s+10));
@@ -47,4 +64,21 @@ int main()
4764
test(bidirectional_iterator<const char*>(s), bidirectional_iterator<const char*>(s+1));
4865
test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s+1));
4966
test(s, s+1);
67+
}
68+
#if TEST_STD_VER > 14
69+
{
70+
constexpr const char* s = "1234567890";
71+
static_assert( constexpr_test(input_iterator<const char*>(s), 10, input_iterator<const char*>(s+10)), "" );
72+
static_assert( constexpr_test(forward_iterator<const char*>(s), 10, forward_iterator<const char*>(s+10)), "" );
73+
static_assert( constexpr_test(bidirectional_iterator<const char*>(s), 10, bidirectional_iterator<const char*>(s+10)), "" );
74+
static_assert( constexpr_test(random_access_iterator<const char*>(s), 10, random_access_iterator<const char*>(s+10)), "" );
75+
static_assert( constexpr_test(s, 10, s+10), "" );
76+
77+
static_assert( constexpr_test(input_iterator<const char*>(s), input_iterator<const char*>(s+1)), "" );
78+
static_assert( constexpr_test(forward_iterator<const char*>(s), forward_iterator<const char*>(s+1)), "" );
79+
static_assert( constexpr_test(bidirectional_iterator<const char*>(s), bidirectional_iterator<const char*>(s+1)), "" );
80+
static_assert( constexpr_test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s+1)), "" );
81+
static_assert( constexpr_test(s, s+1), "" );
82+
}
83+
#endif
5084
}

libcxx/test/std/iterators/iterator.primitives/iterator.operations/prev.pass.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,25 @@ test(It i, It x)
3131
assert(std::prev(i) == x);
3232
}
3333

34+
#if TEST_STD_VER > 14
35+
template <class It>
36+
constexpr bool
37+
constexpr_test(It i, typename std::iterator_traits<It>::difference_type n, It x)
38+
{
39+
return std::prev(i, n) == x;
40+
}
41+
42+
template <class It>
43+
constexpr bool
44+
constexpr_test(It i, It x)
45+
{
46+
return std::prev(i) == x;
47+
}
48+
#endif
49+
3450
int main()
3551
{
52+
{
3653
const char* s = "1234567890";
3754
test(bidirectional_iterator<const char*>(s+10), 10, bidirectional_iterator<const char*>(s));
3855
test(random_access_iterator<const char*>(s+10), 10, random_access_iterator<const char*>(s));
@@ -41,4 +58,18 @@ int main()
4158
test(bidirectional_iterator<const char*>(s+1), bidirectional_iterator<const char*>(s));
4259
test(random_access_iterator<const char*>(s+1), random_access_iterator<const char*>(s));
4360
test(s+1, s);
61+
}
62+
#if TEST_STD_VER > 14
63+
{
64+
constexpr const char* s = "1234567890";
65+
static_assert( constexpr_test(bidirectional_iterator<const char*>(s+10), 10, bidirectional_iterator<const char*>(s)), "" );
66+
static_assert( constexpr_test(random_access_iterator<const char*>(s+10), 10, random_access_iterator<const char*>(s)), "" );
67+
static_assert( constexpr_test(s+10, 10, s), "" );
68+
69+
static_assert( constexpr_test(bidirectional_iterator<const char*>(s+1), bidirectional_iterator<const char*>(s)), "" );
70+
static_assert( constexpr_test(random_access_iterator<const char*>(s+1), random_access_iterator<const char*>(s)), "" );
71+
static_assert( constexpr_test(s+1, s), "" );
72+
}
73+
#endif
74+
4475
}

0 commit comments

Comments
 (0)