【问题标题】:Is there a hoist-free version of BOOST_FOREACH?是否有 BOOST_FOREACH 的无提升版本?
【发布时间】:2011-07-06 18:03:04
【问题描述】:

我知道 BOOST_FOREACH 的“提升”pitfall 缓存了结束迭代器。但是似乎:

  1. 在循环中修改序列相当普遍(尤其是 push_back)
  2. 提供一个没有提升的 BOOST_FOREACH 版本并不难,因此不受修改问题的影响。

显然,在这些情况下,人们通常只是手动编写循环,但我的问题是:

  • 是否存在这样的版本?像 BOOST_FOREACH_NOHOIST 之类的东西。

到目前为止,我一直找不到。

注意:为回应史蒂夫·杰索普而编辑

【问题讨论】:

    标签: c++ templates boost macros foreach


    【解决方案1】:

    “在循环中修改序列相当普遍”

    避免提升不会使宏免受修改问题的影响,因为 BOOST_FOREACH 还在幕后使用了一个移动迭代器,这可能会被 push_back 无效(例如,您正在使用一个向量并且它会重新分配)或其他结构修改。如果您要与之比较的东西不再有效,那么获得一个新的、有效的 end 迭代器并没有多大用处。

    在我看来,提供一些显然在结构修改方面存在问题的东西是合理的。陷阱说,“如果这样做会导致迭代器变得无效,请不要这样做。改用常规的 for 循环。”,而没有指定 哪些 迭代器需要保持有效。如果您的操作可能会破坏 any 迭代器,请使用 for 循环。

    提供有时有问题的东西,这取决于修改的性质,这意味着宏必须记录哪些修改是可以的,哪些不是(如果仅通过描述隐藏的迭代器并说,“不要使那个无效,但你可以使其他迭代器无效”),这开始成为一个尴尬的 API。从一个用户的样本中,100% 的人认为它会免疫,所以我不确定它是否是一个非常直观的界面。

    也就是说,我认为您是对的,BOOST_FOREACH 可以轻松保证它只包含 (1) 结束迭代器,加上 (2) 指向当前迭代的迭代器。因此,如果您有一个无提升版本,带有 (2) 而不是 (1),那么您需要做的就是确保您不会使当前迭代器无效。不过,我认为它不存在,该陷阱的作者似乎认为结束迭代器是失效危险的一部分,而不是试图区分不同类型的失效。我认为 BOOST_FOREACH 旨在作为 std::for_each 在 Boost.Range 上的改进语法,并满足该目标。您总是可以向相关的 Boost 人员建议它可能不止于此。

    【讨论】:

    • “提供有时会出现问题的东西”——我可能同意接受 stl 容器一般都有这个问题。也许我应该在标题中去掉“修改安全”。
    • @Catskul:当然,任何标准算法都是一样的,除了它们都显式提升,因为您将结束迭代器作为参数传递,因此永远不会出现对 nohoist 版本的需求。您应该遵循与 BOOST_FOREACH 相同的规则 - 您不确切知道存在哪些迭代器值,尤其是对于比 InputIterator 更好的迭代器,因此不要在算法期间使任何内容无效。如果你想使迭代器无效,要么通过标准非常仔细地工作以找到你需要的保证,要么不要使用隐藏迭代器的算法,编写一个循环......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-08
    • 1970-01-01
    • 2023-01-04
    • 2015-01-21
    • 2019-04-01
    • 1970-01-01
    相关资源
    最近更新 更多