C++:错误:在“class std::result_of<void (*(std::unordered_map)”中没有名为“type”的类型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28950835/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 21:07:23  来源:igfitidea点击:

c++: error: no type named ‘type’ in ‘class std::result_of<void (*(std::unordered_map

c++multithreadingc++11

提问by user2847598

Following is just a simple program to test using two threads to insert a hash table. For test no lock is used.

下面只是一个简单的程序来测试使用两个线程插入一个哈希表。测试时不使用锁。

#include <iostream>
#include <unordered_map>
#include <thread>

using namespace std;

void thread_add(unordered_map<int, int>& ht, int from, int to)
{
    for(int i = from; i <= to; ++i)
        ht.insert(unordered_map<int, int>::value_type(i, 0));
}

void test()
{
    unordered_map<int, int> ht;
    thread t[2];

    t[0] = thread(thread_add, ht, 0, 9);
    t[1] = thread(thread_add, ht, 10, 19);

    t[0].join();
    t[1].join();

    std::cout << "size: " << ht.size() << std::endl;
}

int main()
{
    test();
    return 0;
}

However, there are errors when compiling it.

但是,编译时出现错误。

$ g++ -std=c++11 -pthread test.cpp
...
/usr/include/c++/4.8.2/functional:1697:61: error: no type named ‘type' in ‘class std::result_of<void (*(std::unordered_map<int, int>, int, int))(std::unordered_map<int, int>&, int, int)>'
       typedef typename result_of<_Callable(_Args...)>::type result_type;
...

Took a while but still cannot correct it. Thanks.

花了一段时间,但仍然无法纠正它。谢谢。

回答by Christophe

I could compile your code successfully with MSVC2013. However, thread()works passing copies of its argument to the new thread. This means that if your code would compile on your compiler, each thread wourd run with its own copy of ht, so that at the end, main's htwould be empty.

我可以使用 MSVC2013 成功编译您的代码。但是,thread()可以将其参数的副本传递给新线程。这意味着,如果您的代码将在您的编译器上编译,则每个线程都将使用其自己的 副本运行ht,因此最终main'sht将为空。

GCC doesn't compile with this weird message. You can get rid of it by using the reference wraper with thread:

GCC 不会用这个奇怪的消息编译。您可以通过使用带有线程的引用包装器来摆脱它:

t[0] = thread(thread_add, std::ref(ht), 0, 9);
t[1] = thread(thread_add, std::ref(ht), 10, 19);

This will compile succesfully. And each reference used by the threads would refer to the same object.

这将成功编译。线程使用的每个引用都将引用同一个对象。

However, there are high chances that you'll get some runtime error or unexpected results. This is because two threads are concurently trying to insert into ht. But unordered_mapis not thread safe, so these racing conditionsmight cause htto reach an unstable state (i.e. UB, i.e. potential segfault).

但是,您很可能会遇到一些运行时错误或意外结果。这是因为两个线程同时尝试插入到ht. 但unordered_map不是线程安全的,因此这些竞争条件可能会导致ht达到不稳定状态(即 UB,即潜在的段错误)。

To make it running properly, you have to protect your concurent accesses:

为了使其正常运行,您必须保护您的并发访问:

#include <mutex>
...
mutex mtx;   // to protect against concurent access

void thread_add(unordered_map<int, int>& ht, int from, int to)
{
    for (int i = from; i <= to; ++i) {
        std::lock_guard<std::mutex> lck(mtx);  // protect statements until end of block agains concurent access
        ht.insert(unordered_map<int, int>::value_type(i, 0));
    }
}

回答by Angew is no longer proud of SO

The error is very cryptic indeed, but the problem is that thread_addtakes its first parameter by reference, but you're passing it by value. This causes the functor type to be deduced wrong. If you want to pass something actually by reference to a functor like std::bindor the main function of a std::thread, you need to use a reference wrapper (std::ref):

该错误确实非常神秘,但问题是thread_add通过引用获取其第一个参数,但您是通过值传递它。这会导致函子类型被推导出错误。如果你想通过引用类似的函子std::bind或 a 的主函数来实际传递一些东西std::thread,你需要使用引用包装器(std::ref):

void test()
{
    // ...

    t[0] = thread(thread_add, std::ref(ht), 0, 9);
    t[1] = thread(thread_add, std::ref(ht), 10, 19);

    // ...
}

[Live example]

[活生生的例子]