#c #gcc #c 20 #c -concepts #range-v3
#c #gcc #c 20 #c -концепции #диапазон-v3
Вопрос:
Пока я пытаюсь понять фиаско концепции требований к алгоритму std ::ranges от ostream_joiner, я обнаружил, что реализация слабовыражаемого итератора GCC выглядит несколько иначе, чем стандартная.
GCC 10.2 stdlibc «iterator_concept.h» определяет слабый_временный итератор, также требует
- moveable
- __is_signed_integer_like<iter_difference_t<_Iter>>
который, по-видимому, требует Iter::different_type является целым со знаком или может быть «long long».
template<typename _Tp> requires requires { typename _Tp::difference_type; }
struct incrementable_traits<_Tp>
{ using difference_type = typename _Tp::difference_type; };
template<typename _Tp>
requires (!requires { typename _Tp::difference_type; }
amp;amp; requires(const _Tpamp; __a, const _Tpamp; __b)
{
requires (!is_void_v<remove_pointer_t<_Tp>>); // PR c /78173
{ __a - __b } -> integral;
})
struct incrementable_traits<_Tp>
{
using difference_type
= make_signed_t<decltype(std::declval<_Tp>() - std::declval<_Tp>())>;
};
...
template<typename _Tp>
using iter_difference_t = __detail::__iter_diff_t<remove_cvref_t<_Tp>>;
...
using __max_diff_type = long long;
...
template<typename _Tp>
concept __is_signed_integer_like = signed_integral<_Tp>
|| same_as<_Tp, __max_diff_type>;
...
/// Requirements on types that can be incremented with .
template<typename _Iter>
concept weakly_incrementable = default_initializable<_Iter>
amp;amp; movable<_Iter>
amp;amp; requires(_Iter __i)
{
typename iter_difference_t<_Iter>;
requires __detail::__is_signed_integer_like<iter_difference_t<_Iter>>;
{ __i } -> same_as<_Iteramp;>;
__i ;
};
Это кажется более строгим, чем полурегулярным в стандарте, который требует только std::copyable .
Почему? Какие преимущества они дают?
Нормально ли / возможно / следует ли писать ostream_joiner, который удовлетворяет слабовыражаемому итератору?
Комментарии:
1. Потому что так сказано в стандарте . В чем, собственно, заключается «фиаско»?
2.@T.C. О, действительно. Существуют оба exp::ranges::слабовыражаемый en.cppreference.com/w/cpp/experimental/ranges/iterator /… и std::weakly_incrementable en.cppreference.com/w/cpp/iterator/weakly_incrementable уже. В любом случае, почему они заменили на moveable и решили не определять «полурегулярный»? Что касается фиаско, ostream_joiner нельзя использовать в качестве итератора с алгоритмами диапазонов. Однако теперь я вижу, что ostream_iterator теперь удовлетворяет требованию std::default_initializable, в то время как ostream_joiner еще не добавил свой конструктор по умолчанию.
3. @T.C. Можно ли просто добавить конструктор по умолчанию в ostream_joiner для использования с алгоритмами диапазонов?