Удовлетворение std :: range :: range concept - PullRequest
4 голосов
/ 27 сентября 2019

В следующих диапазонах C ++ 20 будет использоваться концепция диапазона со следующим определением:

template< class T >
concept range = __RangeImpl<T&>; // exposition-only definition

template< class T >
concept __RangeImpl = requires(T&& t) {
  ranges::begin(std::forward<T>(t)); // equality-preserving for forward iterators
  ranges::end  (std::forward<T>(t));
};

template< class T >
concept __ForwardingRange = ranges::range<T> && __RangeImpl<T>;

Если перевести это на простой английский, я бы сказал, что единственное требованиедля того, чтобы тип удовлетворял концепции диапазона, он должен вызываться с помощью range :: begin и range :: end.

Однако, если я создаю пустой тип только с началом и концом, статическое утверждение для концепции диапазона терпит неудачу?

namespace ranges = std::experimental::ranges;

struct A {
  void begin() {}
  void end() {}
};

static_assert(ranges::range<A>);

Чего мне не хватает?

1 Ответ

3 голосов
/ 27 сентября 2019

Per [range.access.begin] : (выделено)

Имя ranges​::​begin обозначает объект точки настройки .Выражение ranges​::​​begin(E) для некоторого подвыражения E эквивалентно выражению:

  • [...]

  • В противном случае, если E является lvalue, decay-copy(E.begin()), если оно является допустимым выражением и его тип I models input_­or_­output_­iterator.

  • [...]

С вашим A, A.begin() имеет тип void, который не может быть итератором.Следовательно, ranges::begin(std::declval<A>()) недопустимо.

...