Soru c ++: error: st class std :: result_of

Aşağıda, bir karma tablo eklemek için iki iş parçacığı kullanarak sınamak için basit bir programdır. Test için kilit kullanılmaz.

#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;
}

Ancak, derlerken hatalar var.

$ 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;
...

Bir süre aldı ama hala düzeltemez. Teşekkürler.


25
2018-03-09 20:06


Menşei


olası kopyaları: stackoverflow.com/questions/8299545/... ilgili: stackoverflow.com/questions/5116756/... - Ciro Santilli 新疆改造中心 六四事件 法轮功


Cevaplar:


Kodunuzu MSVC2013 ile başarıyla derleyebilirim. Ancak, thread() argümanın kopyalarını yeni iş parçacığına geçirerek çalışır. Bu, kodunuz derleyicinizde derlenecek olursa, her iş parçacığının kendi kopyasıyla çalıştırılacağı anlamına gelir. htsonunda öyle olsun main'ler ht boş olurdu.

GCC bu garip mesajla derleme yapmıyor. Konuyla birlikte referans sarmalayıcıyı kullanarak ondan kurtulabilirsiniz:

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

Bu başarılı bir şekilde derlenecek. Ve iş parçacıkları tarafından kullanılan her başvuru aynı nesneyi ifade eder.

Ancak, bazı çalışma zamanı hatası veya beklenmedik sonuçlar alacağınız için büyük olasılıklar vardır. Bunun nedeni, iki iş parçacığının tutarlı bir şekilde araya girmeye çalışmasıdır. ht. Fakat unordered_map iş parçacığı güvenli değil, bu yüzden yarış koşulları sebep olabilir ht Kararsız bir duruma (yani UB, yani potansiyel segfault) ulaşmak için.

Düzgün çalışmasını sağlamak için, uyumlu erişiminizi korumalısınız:

#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));
    }
}

31
2018-03-09 21:05



Burada msvc hata olduğunu unutmayın. - Yakk - Adam Nevraumont


Hata gerçekten çok şifreli, ama sorun şu ki thread_add ilk parametresini referans olarak alır, ancak değeri ona göre geçirirsiniz. Bu, functor tipinin yanlış çıkarılmasına neden olur. Eğer bir fiile benzer bir şekilde geçmek istiyorsanız std::bind veya bir ana işlevi std::threadbir referans sarıcı kullanmanız gerekir (std::ref):

void test()
{
    // ...

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

    // ...
}

[Canlı örnek]


21
2018-03-09 20:50



Btw, clang çok daha iyi değil (silinen bir işlevi kullanmaya teşebbüs et), ama en azından, parametreler tuple paketinin açıldığı yere götürür, sanırım bir şey. - WhozCraig
İlgisiz, ancak referans ile geçen bir veri yarışını oluşturacaktır ht. - Snps
@Snps OP'in "Test için kilit yok" ifadesini "canlı" olduğunda bir kilit sağlamayı amaçladıkları için aldım. - Angew