我已经编写了类似迭代器的类,由于某种原因,它没有通过Range v3中定义的Readable概念。我不知道为什么,我正在尝试确切地了解我需要
修改语法(和语义)以实现概念。

根据范围v3可读的迭代器的最低语法要求是什么?可以编写一组必须编译的语句吗? (请参见下面的示例)

我有一个迭代器It,可以使用它进行基本操作(我称之为“可读”),但是它没有通过概念检查:

#include <range/v3/all.hpp>
...
    It i; // ok
    typename It::value_type val = *i; // ok
    typename It::reference ref = *i;   // ok
    typename It::value_type val2{ref}; // ok
    static_assert( ranges::CommonReference<typename It::reference&&, typename It::value_type&>{} ); // ok
    static_assert( ranges::Readable<It>{} ); // error: static assertion failed

我还能写哪些其他涉及i的构造来使It不可读? 换句话说,如果迭代器是Range v3可读的,那么什么通用代码将仅且仅会编译?

在很多地方,它说“如果它的行为像指针,那么它是可读的”,但是我找不到我的迭代器出了什么问题。当我看到需要编译什么代码时,我将能够理解哪里出了问题。

我正在尝试调试为什么我的迭代器无法完成概念(因此被范围v3函数拒绝)。注意,Itstd::vector<bool>::iterator都可以使用。

Range v3的可读概念代码https://ericniebler.github.io/range-v3/structranges_1_1v3_1_1concepts_1_1_readable.htmlhttps://en.cppreference.com/w/cpp/experimental/ranges/iterator/Readable类似

(我使用的版本是0.5.0 [Fedora30])
template < class In >

concept bool Readable =
  requires {
    typename ranges::value_type_t<In>;
    typename ranges::reference_t<In>;
    typename ranges::rvalue_reference_t<In>;
  } &&
  CommonReference<ranges::reference_t<In>&&, ranges::value_type_t<In>&> &&
  CommonReference<ranges::reference_t<In>&&, ranges::rvalue_reference_t<In>&&> &&
  CommonReference<ranges::rvalue_reference_t<In>&&, const ranges::value_type_t<In>&>;

因此,看起来迭代器必须(或可以推断出)从value_t<It>提取的It::value_type和从reference_t<It>提取的It::reference

我不知道如何推导rvalue_reference_tCommonReference在语法约束方面的含义。

最佳答案

为了使迭代器在range-v3中建模Readable,它需要:

  • 可通过有意义的operator *取消引用
  • 具有readable_traits的特殊化,或者具有定义关联值类型的公共(public)成员类型value_typeelement_type

  • 我能想到的最简单的Readable用户定义类型是:
    #include <range/v3/all.hpp>
    
    template <typename T>
    class It
    {
    public:
      using value_type = T;
    
    private:
      T x;
    
    public:
      T operator *() const { return x; }
    };
    
    static_assert( ranges::Readable<It<int>>{} );
    

    使用range-v3版本0.3.5(https://godbolt.org/z/JMkODj)可以干净地编译。

    在range-v3的版本1中,Readable不再是类型,而是可转换为constexprbool值,因此在这种情况下的正确断言应为:
    static_assert( ranges::Readable<It<int>> );
    
    value_typeoperator *返回的值不必相同。但是,它们必须在某种意义上可以相互转换,以使算法起作用。这就是CommonReference概念发挥作用的地方。该概念基本上要求两种类型共享一个“公共(public)引用类型”,并且两种类型都可以转换为该类型。它实质上代表common_reference类型的traits,其行为在cppreference中进行了详细描述(但是请注意,那里描述的是TS范围内的内容,可能与范围内的内容不完全相同- v3库)。

    实际上,可以通过以运算符*返回的类型定义转换运算符来满足Readable概念。这是一个通过测试(https://godbolt.org/z/5KkNpv)的简单示例:
    #include <range/v3/all.hpp>
    
    template <typename T>
    class It
    {
    private:
      class Proxy
      {
      private:
        T &x;
    
      public:
        Proxy(T &x_) : x(x_) {}
    
        operator T &() const { return x; }
      };
    
    public:
      using value_type = T;
    
    private:
      T x;
    
    public:
      Proxy operator *() { return {x}; }
    };
    
    static_assert( ranges::Readable<It<bool>>{} );
    

    关于c++ - Range v3中的Readable概念到底是什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56801190/

    10-12 20:50