当前位置: 首页 > 知识库问答 >
问题:

与视图一起使用的自定义容器类型的要求

有凯泽
2023-03-14

我开始玩< code>std::ranges并想了解视图实际上是如何工作的。所以我尝试编写自己的容器和迭代器类型,并希望在视图中使用它。

但是似乎缺少了一些东西,但编译器只告诉我视图中没有start()方法,但没有说明原因。

例子:

#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
}

使用编译

主要的cpp:90:16:error:“struct std::ranges::views::__adaptor::_RangeAdaptorClosurestd::range::views::__adappor::_RangeAdaptor”

https://godbolt.org/z/doW76j

共有1个答案

张毅
2023-03-14

我的迭代器不会对标准::input_or_output_iterator进行建模,因为:

  • 它需要是默认可构造的。
  • 标准::iter_difference_t

MyIterator不是std::sentinel_for

MyIterator不满足std::input_iterator,这需要std::iter_value_t有效。

修复上述所有问题:

#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
}

如果static_assert容器/迭代器必须建模的每个概念,错误消息会更清晰。

 类似资料:
  • 如何使用Apache Thrift编写自定义容器类型? 我知道,在默认情况下,Thrift中的任何map声明都会扩展HashMap。 是否有一种方法可以修改它以扩展ConvoltHashMap而不是HashMap? 例如,if测试。节俭的定义如下: 结构测试数据{1:字符串id,2:地图详细信息} 如何确保此映射作为ConcurrentHashMap实现? 谢谢

  • 如何将此迭代器与泛型类型一起使用?以下是我在“main”函数中尝试的方法: 结果是:<代码>无法从静态上下文引用非静态类项 结果是:<代码>无法从静态上下文引用非静态类项 结果: 编辑: 我调用的是类而不是方法。这项工作: 迭代器it=deq。迭代器(); 我认为,由于iterator()中返回的实例的类型是ListIterator,因此我需要使用该类型声明“it”。

  • 我正在使用Jooq(与PostgreSQL一起使用)。我需要在一些查询中使用,从自定义类型的字段聚合值。 FIELD2是DB中的列,通常映射为Java Long。 我定义了一个强制转换到某个Java类。 转换在所有查询中都能正常工作,但是当使用时,它会异常失败: 有解决办法吗?这是JOOQ限制吗? 谢谢丹

  • 我一直在尝试实现RESTFul体系结构,但我完全搞不清自定义媒体类型是好是坏。 目前,我的应用程序使用Http-Link:header传递“链接”。这很好,我将其与title属性一起使用,允许服务器描述这个“动作”到底是什么,尤其是当呈现给用户时。 我感到困惑的是是否应该指定自定义mime类型。例如,我有一个用户的概念。它可能与当前资源相关联。我要编一个例子,说我有一件拍卖品。我们可能有一个用户在

  • 1.1 类定义 Python 使用 class 关键字来定义类。类名的首字母一般使用大写。 class 类名: 定义了类之后,可以用来实例化对象,并通过“对象名.成员”的方式来访问其中的数据成员或方法。实例化对象如下: 变量 = 类名() 可以使用内置方法 isinstance() 测试一个对象是否为某个类的实例。最后,Python 提供一个 pass 关键字,类似于空语句

  • 问题内容: 我知道Android 很棒。它使我们能够播放本地文件以及媒体流。而且非常容易使用(例如): 通过调用具有不同参数集的重载,可以设置不同类型的DataSource 。这个函数有一个有趣的原型: 看起来可以用自己的实现完全覆盖。它确实有效: 并在主要代码中: 是的,这很好。但是,如果我尝试音频/ aacp广播流(例如:“ http://111.223.51.8:8005”-它是“ COOL