有没有办法在传递给标准算法的谓词中获取元素的偏移量?

Is there a way to get element's offset in predicates passed to std algorithms?

Algorithms library 中使用的 predicates/operators 接受相应迭代器的 value_type 的元素。我想编写一个使用元素在范围内的偏移量的谓词。

例如,考虑以下 code

#include <algorithm>
#include <vector>

int main() {
    std::vector<int> v{0, 1, 2, 3, 4, 5, 6};

    auto offset_value_mismatch = [&v](int const & x){
        return (x != (&x-&v.front()));
    };

    return std::any_of(v.begin(), v.end(), offset_value_mismatch);
}

我的问题是:

  1. 是否有一种“不错”的方法(即比我上面介绍的方法更好)来找到元素在范围内的偏移量?
  2. 是否保证上述技术适用于任何数据类型(代替 int)?因为 const & 可以绑定到一个 r 值,所以我担心我可能会得到一些临时副本的地址。
  3. 可以为关联(非连续)数据结构实现类似的东西吗?
  4. 如果我使用接受 std::ExecutionPolicy 的算法重载,任何答案都会改变吗?

编辑:

有关我的问题的更多信息: 考虑在 std::vector 之上创建的多维数据结构。在此数据结构中,索引是“托管的”,因此我可以同时对所有数据结构执行某些操作。此外,数据类型本身可以是索引。

因此,当我修改索引时,我需要知道“域”索引和“范围”索引之间是否存在某种关系。

至此,我用了一个循环。我想看看我是否可以通过使用标准的并行算法来提高性能。


编辑#2:

我最终实现了一个简单的基于顺序循环的算法,用于(罕见的)特定索引类型同时出现在域和范围中的情况。 对于其他情况,上述练习是不必要的,我使用 par_unseq 执行策略获得了大约 60% 的加速! (但出于某种原因,par 没有)。

Is the technique above guaranteed to work for any data type (in place of int)? Because const & can bind to an r-value I'm worried I might get the address of some temporary copy.

没有。这仅适用于 std::vectorstd::array 或保证所有元素都存储在连续内存中的原始指针。对于他们来说,它适用于存储在那里的任何数据类型。但是,即使对于 std::deque 中的随机访问迭代器,这种技术也会导致 UB。

Can something similar be implemented for associative data structures?

我怀疑,因为这甚至不适用于随机访问迭代器,例如前向迭代器的情况会更糟,看起来你有 XY 问题并且需要指定你想要实现的目标。

  1. Is there a "nice" way (i.e. better than what I presented above) to find the element's offset in the range?

不,一般情况下不会。

  1. Is the technique above guaranteed to work for any data type

几乎(除非您显然必须更改参数的类型以对应于正在迭代的任何数据类型)。您必须使用 std::addressof 才能使其与重载 addressof 运算符的类型一起使用(但谁会这样做?)。

  1. Can something similar be implemented for associative data structures?

不太像。您所展示的内容有效,但仅适用于连续的迭代器,即数组的迭代器(一般意义上,包括向量和字符串)。

假设你正在使用一个按顺序迭代元素的算法(这就是执行策略确实重要的地方),那么一个通用的解决方案是使用累加器:

auto offset_value_mismatch = [](auto& x) {
    static int i;
    return i++ == x;
}
  1. Do any of the answers change if I use the algorithm overloads accepting an std::ExecutionPolicy?

地址减法和累加器都只适用于顺序算法,不适用于并行算法。从技术上讲,可以使用锁使累加器与并行策略(但不是无序的)一起工作,但据我所知这样做没有任何优势。