如果容器不是调用函数中的引用,则通过std :: thread将引用传递给迭代器失败

时间:2019-06-05 14:56:29

标签: c++ multithreading reference stl iterator

这是我的问题:

我有一个包含容器成员的课程,例如std::vector。我有一个有趣的功能,例如parallelStuff,它使用引用对该容器的迭代器进行处理。我想使用std::thread

并行执行上述功能

我已经实现了,效果很好。现在,我想编写一个非常相似的设置,但有一个小的区别:在工作版本中,在调用parallelStuff上的线程的函数中,我从对容器的引用中获得了迭代器。

但是,如果我从非引用容器中获得了迭代器,则编译会失败。

这是一个复制问题的最小示例:

#include <thread>
#include <vector>

class Foo {
public:
    Foo() {}
    auto const & member() { return member_; }
    void parallelStuff(std::vector<int>::const_iterator & it,
                       std::vector<int>::const_iterator const & end) {
        // do stuff while it != end
    }
private:
    std::vector<int> member_;
};


int main(int argc, char * argv[]) {
    auto foo = Foo();
    auto& member = foo.member();
    // auto member = foo.member();  <-- copy instead of reference, this fails!
    auto it = member.begin();
    auto end = member.end();
    auto t = std::thread(&Foo::parallelStuff, &foo,
                         std::ref(it), std::ref(end));
    t.join();

    return 0;
}

如前所述,如果我使用member的副本而不是引用,则会出现错误

/usr/include/c++/8/thread:120:17: error: static assertion failed: std::thread arguments must be invocable after conversion to rvalues

谷歌搜索错误消息只会导致我进入site,这说明我需要将参考参数包装在已经完成的std::ref()中。

有人知道这里出了什么问题吗,请解释一下(以及解决方法)?

非常感谢!

PS:我将gcc version 8.3.0 (Ubuntu 8.3.0-6ubuntu1~18.04)-std=c++17一起使用

1 个答案:

答案 0 :(得分:1)

函数parallelStuff希望获得 const迭代器,而您必须提供它们。

您可以获得 const迭代器

  1. 通过在对象上调用cbegin / cend

  1. 通过在 const对象
  2. 上调用begin / end

在下面的行

auto member = foo.member();

自动类型推断的工作原理是从初始值设定项中删除引用性和常量性。因此member仅声明为vector<int>。因此,begin / end返回vector<int>::iteratorparallelStuff的参数不匹配的内容。

要获取非常量对象上的 const迭代器,只需调用cbegin / cend

auto it = member.cbegin();
auto end = member.cend();

LIVE DEMO


这有效

auto& member

因为推论memberconst vector<int>&,所以在常量对象上调用的begin / end返回了与{{1 }}声明。