Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

requirements for custom container type to use with views

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

like image 651
Klaus Avatar asked Sep 08 '20 08:09

Klaus


People also ask

What are the OS requirements for a Windows container?

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.

What are the requirements to use a container in prism?

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.

What versions of Windows Server have the windows container feature?

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:.

What are the Hyper-V container host requirements for nested virtualization?

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.


1 Answers

MyIterator does not model std::input_or_output_iterator because:

  • It needs to be default constructible.
  • std::iter_difference_t<MyIterator> must be valid, and
  • the pre-increment operator must return a reference.

MyIterator 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.

like image 118
metalfox Avatar answered Oct 16 '22 08:10

metalfox