Range-v3:使用view_facade提供const和非const迭代器

时间:2015-07-15 02:33:07

标签: c++ range-v3

我无法使用view_facade(来自range-v3)创建一个提供const和非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迭代器。我怎样才能做到这一点?

1 个答案:

答案 0 :(得分:9)

view_facade用于构建视图。观点是指他们不拥有的数据。它们就像指针一样在逻辑上它们是间接的。和指针一样,顶级const 对所引用数据的const没有影响。这是您取消引用int*还是int*const,结果是相同的:int&

您的观点不是一种观点。它拥有自己的数据。 (请参阅vector<int> ints_数据成员。)尝试使用view_facade将此数据结构转换为视图必然会导致挫败感。这非常符合设计。视图与容器不同。对不起,Range-v3库没有容器外观。

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