我可以在输入迭代器上定义开始和结束吗?

Tim*_*imo 3 c++ c++20

假设我有一个MyInputIter满足该概念的输入迭代器类型(我用它来遍历树状结构)std::input_iterator

我有什么理由不应该在迭代器本身上定义begin()and吗?end()

struct MyInputIter
{
    // iterator stuff omitted

    auto begin() const { return *this; }
    auto end() const { return MySentinel{}; }
};
Run Code Online (Sandbox Code Playgroud)

原因是我不必创建另一种类型来包装beginend因此我可以在 for 循环中使用它:

MyInputIter iterate(TreeNode root, FilterPattern pattern)
{
    return MyInputIter{ root, pattern };
}

void foo()
{
    for (auto item : iterate(someRandomTreeNode, "*/*.bla"))
        process(item);
}
Run Code Online (Sandbox Code Playgroud)

同时还可以将其用作迭代器:

std::vector<TreeNode> vec(iterate(someRandomTreeNode, "*"), MySentinel{});
Run Code Online (Sandbox Code Playgroud)

eer*_*ika 5

\n

我是否有任何理由不应该在迭代器本身上定义 begin() 和 end() ?

\n
\n

需要考虑的潜在问题:

\n
    \n
  1. 为迭代器实现这些函数可能会很昂贵。要么是因为需要遍历结构来查找它们,要么是因为迭代器中存储了额外的状态。
  2. \n
  3. 它可能会令人困惑,因为它偏离了常见模式。编辑:正如\xe5\xba\xb7\xe6\xa1\x93\xe7\x91\x8b所指出的,范围为 的迭代器有先例std::filesystem::directory_iterator,所以这一般来说可能不是一个重大问题。还有另一个考虑因素是您的范围实施是否按预期方式工作。
  4. \n
\n
\n

原因是我不必创建另一种类型

\n
\n

据我所知,您不需要创建另一种类型。您可以使用:

\n
std::ranges::subrange(MyInputIter{ root, pattern }, MySentinel{})\n
Run Code Online (Sandbox Code Playgroud)\n

  • @Timo:主要缺点是它违反了现有组合迭代器范围对象设置的期望,例如“std::filesystem::directory_iterator”(或任何其他分层集合迭代器),其中“begin()”和“end( )` 返回当前节点的子节点范围,而不是与当前节点处于同一级别的范围。 (2认同)