Вот пример:
std::vector<int> r1 = { 0, 1, 2, 3, 4 };
std::vector<int> r2 = { 5, 6, 7, 8, 9 };
auto view = Views::ConcatView(r1, r2);
for(auto i : view)
{
std::cout << std::format("{} ", i);
}
static_assert(std::ranges::range<decltype(view)>); // false
При этом цикл проходит, но вот концепт не проходит.
Вот
код view
template<view TView, view TOtherView>
requires std::same_as<range_value_t<TView>, range_value_t<TOtherView>>
class ConcatView : public view_interface<ConcatView<TView, TOtherView>>
{
private:
TView _view;
TOtherView _otherView;
class ConcatIterator
{
private:
ConcatView* _parent {};
bool _isInSecond;
iterator_t<TView> _firstIterator;
iterator_t<TOtherView> _secondIterator;
public:
using value_type = range_value_t<TView>;
using difference_type = range_difference_t<TView>;
using reference = range_reference_t<TView>;
constexpr ConcatIterator(ConcatView& parent, bool isEnd):
_parent(&parent),
_isInSecond(false)
{
auto& first = parent._view;
auto& second = parent._otherView;
if(isEnd)
{
_firstIterator = first.end();
_secondIterator = second.end();
_isInSecond = true;
}
else
{
_firstIterator = first.begin();
_secondIterator = second.begin();
if(_firstIterator == first.end())
{
_isInSecond = true;
}
}
}
constexpr reference operator*() const
{
if(_isInSecond)
{
return *_secondIterator;
}
else
{
return *_firstIterator;
}
}
constexpr ConcatIterator& operator++()
{
if(_isInSecond)
{
++_secondIterator;
}
else
{
if(++_firstIterator == _parent->_view.end())
{
_isInSecond = true;
_secondIterator = _parent->_otherView.begin();
}
}
return *this;
}
constexpr ConcatIterator operator++(int)
{
ConcatIterator tmp = *this;
++(*this);
return tmp;
}
constexpr bool operator==(const ConcatIterator& other) const
{
return _isInSecond == other._isInSecond &&
(_isInSecond
? _secondIterator == other._secondIterator
: _firstIterator == other._firstIterator);
}
};
public:
constexpr ConcatView(TView range, TOtherView otherRange):
_view(std::move(range)),
_otherView(std::move(otherRange))
{}
ConcatView(const ConcatView&) requires std::copyable<TView> = default;
ConcatView(ConcatView&&) = default;
constexpr auto begin()
{
return ConcatIterator(*this, false);
}
constexpr auto end()
{
return ConcatIterator(*this, true);
}
constexpr auto size() requires sized_range<TView> && sized_range<TOtherView>
{
return std::ranges::size(_view) + std::ranges::size(_otherView);
}
ConcatView& operator=(const ConcatView&) requires std::copyable<TView> = default;
ConcatView& operator=(ConcatView&&) = default;
};
template<typename TRange, typename TOtherRange>
ConcatView(TRange&&, TOtherRange&&) -> ConcatView<all_t<TRange>, all_t<TOtherRange>>;