【问题标题】:Range-v3: Use view_facade to provide both const and non-const iteratorsRange-v3:使用 view_facade 提供 const 和 non-const 迭代器
【发布时间】:2015-07-15 02:33:06
【问题描述】:

我在使用 view_facade(来自 range-v3)创建同时提供 const 和非常量访问的视图时遇到问题。例如,我尝试修改 view_facade 测试(在 test/view_facade.cpp 中)以允许非 const 访问(默认情况下它只允许 const 访问):

struct MyRange
  : ranges::range_facade<MyRange>
{
private:
    friend struct ranges::range_access;
    std::vector<int> ints_;

    template <bool isConst>
    struct cursor
    {
    private:
        using It = typename std::conditional<isConst, std::vector<int>::const_iterator, std::vector<int>::iterator>::type;
        using RefType = typename std::conditional<isConst, int const&, int&>::type;
        It iter;
    public:
        cursor() = default;
        cursor(It it)
          : iter(it)
        {}
        RefType current() const
        {
            return *iter;
        }
    //...
    };
/*    // Uncommenting these overloads will cause an error, below.
    cursor<true> begin_cursor() const
    {
        return {ints_.begin()};
    }
    cursor<true> end_cursor() const
    {
        return {ints_.end()};
    }
*/
    cursor<false> begin_cursor()
    {
        return {ints_.begin()};
    }
    cursor<false> end_cursor()
    {
        return {ints_.end()};
    }
public:
    MyRange()
      : ints_{1, 2, 3, 4, 5, 6, 7}
    {}
};

int main() {
    MyRange nc;
    int& nci = *nc.begin();  // error here when const overloads present.
}

Full code here.

这适用于 begin_cursor 和 end_cursor 的 const 重载注释掉。但是,如果我重新添加这些重载,则会在指示的行 (GCC 5.1) 上生成以下错误:

error: binding 'const int' to reference of type 'int&' discards qualifiers

似乎在选择 const 版本,给了我一个 const 迭代器。我想要的是:用于 const 对象的 const 迭代器,以及用于非 const 对象的非 const 迭代器。我怎样才能做到这一点?

【问题讨论】:

    标签: c++ range-v3


    【解决方案1】:

    view_facade 用于构建视图。视图指的是他们不拥有的数据。它们就像指针,在逻辑上它们是间接的。和指针一样,顶级const应该对引用数据的const-ness 没有影响。也就是说,无论您取消引用 int* 还是 int*const,结果都是一样的:int&amp;

    你的观点不是观点。它拥有自己的数据。 (请参阅vector&lt;int&gt; ints_ 数据成员。)尝试使用view_facade 将此数据结构转换为视图必然会导致挫败感。这在很大程度上是设计使然。视图不同于容器。 Range-v3 库没有容器外观,抱歉。

    (发生了什么:由于视图表示间接,view_facade 非常努力地使 const 和非 const begin()end() 返回相同的类型。如果存在 cursor_begin() const,那是 总是选择。总是。当这会破坏代码时,通常是因为该代码将容器与视图混淆了。)

    【讨论】:

    • 我想我不明白不拥有其数据的视图是什么意思。我发布的示例几乎直接来自测试,但我实际上试图做的是将指针 + 大小包装在类似范围的界面中。由于视图在分配/释放数据的意义上不拥有指针(它由第三方库管理),我认为 view_facade 是合适的。但是,你的解释是有道理的。谢谢你的回答。
    • 指针/长度对一个视图。 view::counted 正是如此。如果你用指针/长度替换你的vector 成员,事情应该会更好。
    • 啊! view::counted 就是一个很好的例子。不知道我是怎么错过的。
    • “当这破坏了代码时,通常是因为该代码......”已经被破坏了。
    • 虽然容器适配器 有趣且有用(例如,参见 std::stack),但我不确定这是进一步扩大 range-v3 范围的合适时机.我希望花更多的时间来完善和提出已经存在的东西,而不是花更少的时间添加我需要维护的新功能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-04
    相关资源
    最近更新 更多