簡體   English   中英

在 C++23 中編譯迭代器時出現“原子約束依賴於自身”錯誤

[英]"atomic constraint depends on itself" error when compiling iterator in C++23

我正在嘗試制作一個迭代器,它主要逐個字符地傳遞字符串視圖,但有一些特殊情況,我嘗試的是以下內容:

// iter.hpp
#include <string_view>

typedef std::basic_string_view<char> UStringView;

class symbol_iter
{
private:
  UStringView str;
  UStringView::size_type sloc = 0;
  UStringView::size_type eloc = 0;
public:
  symbol_iter(UStringView s);
  symbol_iter(const symbol_iter& other);
  ~symbol_iter();
  UStringView operator*();
  symbol_iter& operator++();
  bool operator!=(const symbol_iter& other) const;
  bool operator==(const symbol_iter& other) const;
  symbol_iter begin();
  symbol_iter end();
};

symbol_iter::symbol_iter(UStringView s) : str(s)
{
  ++*this;
}

symbol_iter::symbol_iter(const symbol_iter& other)
  : str(other.str), sloc(other.sloc), eloc(other.eloc) {}

symbol_iter::~symbol_iter() {}

UStringView symbol_iter::operator*() {
  return str.substr(sloc, eloc-sloc);
}

symbol_iter& symbol_iter::operator++()
{
  if (sloc < str.size()) {
    sloc = eloc;
    eloc++;
    char c = str[sloc];
    if (c == '\\') {
      sloc++;
      eloc++;
    } else if (c == '<') {
      for (auto i = eloc; i < str.size(); i++) {
        if (str[i] == '>') {
          eloc = i + 1;
          break;
        }
      }
    }
    if (eloc > str.size()) eloc = str.size();
  }
  return *this;
}

bool symbol_iter::operator!=(const symbol_iter& o) const
{
  return str != o.str || sloc != o.sloc || eloc != o.eloc;
}

bool symbol_iter::operator==(const symbol_iter& o) const
{
  return str == o.str && sloc == o.sloc && eloc == o.eloc;
}

symbol_iter symbol_iter::begin()
{
  return symbol_iter(str);
}

symbol_iter symbol_iter::end()
{
  symbol_iter ret(str);
  ret.sloc = str.size();
  ret.eloc = str.size();
  return ret;
}

// main.cc
#include "iter.hpp"
#include <iostream>

int main(int argc, char** argv) {
  UStringView name(argv[1]);
  for (auto sym : symbol_iter(name)) {
    std::cout << sym << std::endl;
  }
}

當我在 C++2a 下編譯它時,它完全符合我的預期:

$ g++ --std=c++2a main.cc
$ ./a.out 'xyz<q>'
x
y
z
<q>

但是當我用 C++23 編譯時,我得到了錯誤

/usr/include/c++/11/bits/ranges_base.h:574:21: error: satisfaction of atomic constraint ‘requires(_Tp& __t) {std::ranges::__cust::begin(__t);std::ranges::__cust::end(__t);} [with _Tp = _Range]’ depends on itself
  574 |     concept range = requires(_Tp& __t)
      |                     ^~~~~~~~~~~~~~~~~~
  575 |       {
      |       ~              
  576 |         ranges::begin(__t);
      |         ~~~~~~~~~~~~~~~~~~~
  577 |         ranges::end(__t);
      |         ~~~~~~~~~~~~~~~~~
  578 |       };
      |       ~              

而且我無法通過谷歌搜索找到對此錯誤的任何解釋。

main中的循環顯示了我是如何使用它的(使用auto的 range-for 循環),盡管即使我刪除循環也會出現錯誤(也就是說,即使代碼中沒有任何其他內容引用symbol_iter class)。

此外,如果我將UStringView更改為UStringView* ,除了operator*之外的所有地方(我試過這個,因為在代碼庫的其他地方有一個具有相同接口的迭代器,只是輸入類型是指針而不是視圖,錯誤是固定的)。

根據 ildjarn 和康桐蔚的評論,這似乎是 GCC 先前版本中的錯誤。

更基本的問題,我認為 Nicol Bolas 試圖指出(我最初幾次不理解),是我不應該嘗試為單個 class 創建多個迭代器類型(就像我想要的那樣到),一個以前沒有發現的錯誤,因為碰巧我之前嘗試編寫迭代器並沒有破壞任何東西。

現在適用於兩個編譯器版本的 class 是

class symbol_iter
{
private:
  UStringView str;
public:
  symbol_iter(UStringView s) : str(s) {}
  ~symbol_iter() {}
  class iterator
  {
    friend symbol_iter;
  private:
    UStringView str;
    UStringView::size_type sloc = 0;
    UStringView::size_type eloc = 0;
  public:
    iterator(UStringView s);
    iterator(const iterator& other);
    ~iterator();
    UStringView operator*() const;
    iterator& operator++();
    bool operator!=(const symbol_iter::iterator& other) const;
    bool operator==(const symbol_iter::iterator& other) const;
  };
  iterator begin() const;
  iterator end() const;
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM