I start to play with std::ranges
and want understand how views really work. So I try to write my own container and iterator type and want to use it in a view.
But something seems to be missing but the compiler only tells me that there is no begin()
method inside the view but not why.
Example:
#include <iostream>
#include <array>
#include <ranges>
class MyFixedContainer;
class MyIterator
{
MyFixedContainer* ptr;
unsigned int offset;
public:
MyIterator( MyFixedContainer* ptr_, unsigned int offset_ ): ptr{ ptr_},offset{offset_}{}
bool operator==( MyIterator& other ) const
{
return ( ptr == other.ptr )&& ( offset == other.offset );
}
bool operator!=( MyIterator& other ) const
{
return !(*this == other);
}
MyIterator operator++()
{
offset++;
return *this;
}
MyIterator operator++(int)
{
MyIterator tmp = *this;
offset++;
return tmp;
}
int operator*() const;
};
class MyFixedContainer
{
std::array<int,4> arr={5,6,7,8};
public:
auto begin() { return MyIterator{ this, 0 }; }
auto end() { return MyIterator{ this, 4}; }
int Get( int offset ) const
{
return arr[ offset ];
}
};
int MyIterator::operator*() const
{
return ptr->Get( offset );
}
int main()
{
MyFixedContainer c;
// Container type itself works:
for ( int i: c )
{
std::cout << i << std::endl;
}
// Try to use with std::ranges
auto even = [] (int i) { return 0 == i % 2; };
auto y = std::views::filter(c, even);
auto b = y.begin(); // << error message
}
Compiles with
main.cpp:90:16: error: 'struct std::ranges::views::__adaptor::_RangeAdaptorClosurestd::ranges::views::__adaptor::_RangeAdaptor<_Callable::operator()<{MyFixedContainer&, main()::<lambda(int)>&}>::<lambda(_Range&&)> >' has no member named 'begin' 90 | auto b = y.begin();
https://godbolt.org/z/doW76j
OS requirements. The Windows container feature is only available on Windows Server 2016 (Core and with Desktop Experience), Windows 10 Professional and Enterprise (Anniversary Edition) and later. Windows Server Container hosts must have Windows installed to c:. This restriction does not apply if only Hyper-V isolated containers will be deployed.
Prism imposes the following requirements in order to use a container: The container must support all three Prism platforms (WPF, Uno/WinUI/UWP, Xamarin.Forms) In this topic we will be creating a container extension for the Grace DI container.
The Windows container feature is only available on Windows Server 2016 (Core and with Desktop Experience), Windows 10 Professional and Enterprise (Anniversary Edition) and later. The Hyper-V role must be installed before running Hyper-V isolation. Windows Server Container hosts must have Windows installed to c:.
If a Windows container host will be run from a Hyper-V virtual machine, and will also be hosting Hyper-V Containers, nested virtualization will need to be enabled. Nested virtualization has the following requirements: At least 4 GB RAM available for the virtualized Hyper-V host.
MyIterator
does not model std::input_or_output_iterator
because:
std::iter_difference_t<MyIterator>
must be valid, andMyIterator
is not a std::sentinel_for
<MyIterator, MyIterator>
because its operators ==
and !=
take references instead of const
references.
MyIterator
does not satisfy std::input_iterator
, which requires std::iter_value_t
to be valid.
Fixing all of the above:
#include <iostream>
#include <array>
#include <ranges>
class MyFixedContainer;
class MyIterator
{
MyFixedContainer* ptr;
unsigned int offset;
public:
using difference_type = int;
using value_type = int;
MyIterator() = default;
MyIterator( MyFixedContainer* ptr_, unsigned int offset_ ): ptr{ ptr_},offset{offset_}{}
bool operator==( MyIterator const & other ) const
{
return ( ptr == other.ptr )&& ( offset == other.offset );
}
bool operator!=( MyIterator const & other ) const
{
return !(*this == other);
}
MyIterator &operator++()
{
offset++;
return *this;
}
MyIterator operator++(int)
{
MyIterator tmp = *this;
offset++;
return tmp;
}
int operator*() const;
};
class MyFixedContainer
{
std::array<int,4> arr={5,6,7,8};
public:
auto begin() { return MyIterator{ this, 0 }; }
auto end() { return MyIterator{ this, 4}; }
int Get( int offset ) const
{
return arr[ offset ];
}
};
int MyIterator::operator*() const
{
return ptr->Get( offset );
}
int main()
{
MyFixedContainer c;
// Container type itself works:
for ( int i: c )
{
std::cout << i << std::endl;
}
// Try to use with std::ranges
auto even = [] (int i) { return 0 == i % 2; };
static_assert(std::input_or_output_iterator<MyIterator>);
static_assert(std::ranges::input_range<MyFixedContainer>);
auto y = c | std::views::filter(even);
auto b = y.begin(); // << OK
}
The error messages are much clearer if you static_assert
every concept that your container/iterator has to model.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With