[英]"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.