あぁところで、
template<concept Iterator> concept Range<typename T> { Iterator iterator; iterator begin(T&); iterator end(T&); }; template<typename Rng> requires Range<RandomAccessIterator><Rng> // !? && ShuffleIterator<T::iterator> && LessThanComparable<T> void sort(Rng& range) { std::sort(begin(range), end(range)); }
あらあら。最初書いたときからなんか破綻するよなーと思ってたらこれか。
というわけで、こんな、シンタックスにするとか。
template<typename Rng> requires Rng : Range<RandomAccessIterator> && T::iterator : ShuffleIterator && T::iterator::value_type : LessThanComparable void sort(Rng& range) { std::sort(begin(range), end(range)); }
こっちのほうが型Rngと関連する型それぞれについて要求が分かりやすいと思う。 ただconcept template?のほうは、結局ShuffleIteratorだけ外で要求すると言うのは統一感がなさすぎるなぁ。多分この調子だと、
template<concept C1, concept C2> concept Compose<typename T> { requires T : C1, C2; }; template<typename Rng> requires Rng : Range<Compose<RandomAccessIterator, ShuffleIterator>> && T::iterator::value_type : LessThanComparable void sort(Rng& range) { std::sort(begin(range), end(range));
というようなことになってきて、なんかもうそれならInputIteratorでいいよってなるなぁ。考えれば考えるほどきまりが悪くなってきた。どうしたもんだろう。
二つ以上の型引数を取るconceptについては、
concept Foo<typename T, typename U> {}; concept Bar<typename T, typename U> {}; template<typename T, typename U> requires T, U : Foo, Bar && U, T : Bar void f() {}
とかでいいんじゃないかと思った。
思ったけど今気付いた。conceptが引数に取れるのは何も型だけじゃなかった。はっはっは。つまり現状が一番ということ。スミ(ry