@@ -387,8 +387,128 @@ struct instantiator {
387
387
}
388
388
};
389
389
390
+ template <class T >
391
+ struct difference_type_only_iterator {
392
+ static_assert (is_object_v<T>);
393
+
394
+ friend constexpr bool operator ==(difference_type_only_iterator, difference_type_only_iterator) = default ;
395
+ friend constexpr auto operator <=>(difference_type_only_iterator, difference_type_only_iterator) = default ;
396
+
397
+ using iterator_concept = contiguous_iterator_tag;
398
+ using value_type = remove_cvref_t <T>;
399
+
400
+ constexpr T& operator *() const noexcept {
401
+ return *ptr_;
402
+ }
403
+
404
+ constexpr T* operator ->() const noexcept {
405
+ return ptr_;
406
+ }
407
+
408
+ constexpr difference_type_only_iterator& operator ++() noexcept {
409
+ ++ptr_;
410
+ return *this ;
411
+ }
412
+
413
+ constexpr difference_type_only_iterator operator ++(int ) noexcept {
414
+ auto result = *this ;
415
+ ++*this ;
416
+ return result;
417
+ }
418
+
419
+ constexpr difference_type_only_iterator& operator --() noexcept {
420
+ --ptr_;
421
+ return *this ;
422
+ }
423
+
424
+ constexpr difference_type_only_iterator operator --(int ) noexcept {
425
+ auto result = *this ;
426
+ --*this ;
427
+ return result;
428
+ }
429
+
430
+ constexpr difference_type_only_iterator& operator +=(same_as<ptrdiff_t > auto n) noexcept {
431
+ ptr_ += n;
432
+ return *this ;
433
+ }
434
+
435
+ constexpr difference_type_only_iterator& operator -=(same_as<ptrdiff_t > auto n) noexcept {
436
+ ptr_ -= n;
437
+ return *this ;
438
+ }
439
+
440
+ friend constexpr difference_type_only_iterator operator +(
441
+ difference_type_only_iterator i, same_as<ptrdiff_t > auto n) noexcept {
442
+ i += n;
443
+ return i;
444
+ }
445
+
446
+ friend constexpr difference_type_only_iterator operator +(
447
+ same_as<ptrdiff_t > auto n, difference_type_only_iterator i) noexcept {
448
+ i += n;
449
+ return i;
450
+ }
451
+
452
+ friend constexpr difference_type_only_iterator operator -(
453
+ difference_type_only_iterator i, same_as<ptrdiff_t > auto n) noexcept {
454
+ i -= n;
455
+ return i;
456
+ }
457
+
458
+ friend constexpr ptrdiff_t operator -(difference_type_only_iterator i, difference_type_only_iterator j) noexcept {
459
+ return i.ptr_ - j.ptr_ ;
460
+ }
461
+
462
+ constexpr T& operator [](same_as<ptrdiff_t > auto n) const noexcept {
463
+ return ptr_[n];
464
+ }
465
+
466
+ T* ptr_;
467
+ };
468
+
469
+ template <class T >
470
+ struct difference_type_only_sentinel {
471
+ static_assert (is_object_v<T>);
472
+
473
+ friend constexpr bool operator ==(difference_type_only_iterator<T> i, difference_type_only_sentinel s) noexcept {
474
+ return i.ptr_ == s.ptr_end_ ;
475
+ }
476
+
477
+ friend constexpr ptrdiff_t operator -(difference_type_only_iterator<T> i, difference_type_only_sentinel s) noexcept {
478
+ return i.ptr_ - s.ptr_end_ ;
479
+ }
480
+
481
+ friend constexpr ptrdiff_t operator -(difference_type_only_sentinel s, difference_type_only_iterator<T> i) noexcept {
482
+ return s.ptr_end_ - i.ptr_ ;
483
+ }
484
+
485
+ T* ptr_end_;
486
+ };
487
+
488
+ template <class T >
489
+ constexpr bool test_lwg3717 () {
490
+ remove_cv_t <T> x{};
491
+
492
+ auto cmv_sr = ranges::subrange (difference_type_only_iterator<T>{&x}, difference_type_only_sentinel<T>{&x + 1 })
493
+ | views::common;
494
+
495
+ static_assert (ranges::contiguous_range<decltype (cmv_sr)>);
496
+ static_assert (ranges::contiguous_range<const decltype (cmv_sr)>);
497
+
498
+ assert (ranges::end (cmv_sr) == ranges::begin (cmv_sr) + ptrdiff_t {1 });
499
+ assert (ranges::end (as_const (cmv_sr)) == ranges::begin (as_const (cmv_sr)) + ptrdiff_t {1 });
500
+
501
+ return true ;
502
+ }
503
+
390
504
int main () {
391
505
// Get full instantiation coverage
392
506
static_assert ((test_in<instantiator, const int >(), true ));
393
507
test_in<instantiator, const int >();
508
+
509
+ static_assert (test_lwg3717<int >());
510
+ static_assert (test_lwg3717<const int >());
511
+
512
+ assert (test_lwg3717<int >());
513
+ assert (test_lwg3717<const int >());
394
514
}
0 commit comments