2017-01-24 3 views
0

Ich habe den folgenden Code in MacOS versucht, Kompilierung Fehler zu bekommen. Meine Frage ist, was ist der beste Weg, um Argumente beim Erstellen von Threads an Funktionen übergeben?C++ 11 Multithread Merge Sort

#include <iostream> 
#include <vector> 
#include <thread> 
#include <utility> 
#include <functional> 

void merge(std::vector<int> &v, int l, int m, int r) { 
    int i = l; 
    int j = m + 1; 
    std::vector<int> temp; 
    while (i <= m && j <= r) { 
     if (v.at(i) <= v.at(j)) { 
      temp.push_back(v.at(i++)); 
     } 
     else { 
      temp.push_back(v.at(j++)); 
     } 
    } 
    while (i <= m) { 
     temp.push_back(v.at(i++)); 
    } 
    while (j <= r) { 
     temp.push_back(v.at(j++)); 
    } 
    std::copy(temp.begin(), temp.end(), v.begin() + l); 
} 

void mergesort(std::vector<int> &v, int l, int r) { 
    if (l < r) { 
     int m = (l + r)/2; 
     std::thread sort_thread1(mergesort, std::ref(v), l, m); 
     std::thread sort_thread2(mergesort, std::ref(v), m + 1, r); 
     sort_thread1.join(); 
     sort_thread2.join(); 
     merge(v, l, m, r); 
    } 
} 

int main(void) { 
    int n; 
    std::vector<int> v; 
    std::cin >> n; 
    for (int i = 0; i < n; ++i) { 
     int a; 
     std::cin >> a; 
     v.push_back(a); 
    } 
    mergesort(v, 0, n - 1); 
    for (const int &a : v) { 
     std::cout << a << " "; 
    } 
    std::cout << std::endl; 
    return 0; 
} 

Ich habe versucht, Klirren und g ++ hier aber bekommt den gleichen Fehler wie folgt:

~/Desktop> g++-6 mergesort.cpp -std=c++11 -pthread 
mergesort.cpp: In function 'void mergesort(std::vector<int>&, int, int)': 
mergesort.cpp:31:62: error: no matching function for call to 'std::thread::thread(<unresolved overloaded function type>, std::reference_wrapper<std::vector<int> >, int&, int&)' 
     std::thread sort_thread1(mergesort, std::ref(v), l, m); 
                  ^
In file included from mergesort.cpp:3:0: 
/usr/local/Cellar/gcc/6.3.0_1/include/c++/6.3.0/thread:128:7: note: candidate: template<class _Callable, class ... _Args> std::thread::thread(_Callable&&, _Args&& ...) 
     thread(_Callable&& __f, _Args&&... __args) 
     ^~~~~~ 
/usr/local/Cellar/gcc/6.3.0_1/include/c++/6.3.0/thread:128:7: note: template argument deduction/substitution failed: 
mergesort.cpp:31:62: note: couldn't deduce template parameter '_Callable' 
     std::thread sort_thread1(mergesort, std::ref(v), l, m); 
                  ^
In file included from mergesort.cpp:3:0: 
/usr/local/Cellar/gcc/6.3.0_1/include/c++/6.3.0/thread:123:5: note: candidate: std::thread::thread(std::thread&&) 
    thread(thread&& __t) noexcept 
    ^~~~~~ 
/usr/local/Cellar/gcc/6.3.0_1/include/c++/6.3.0/thread:123:5: note: candidate expects 1 argument, 4 provided 
/usr/local/Cellar/gcc/6.3.0_1/include/c++/6.3.0/thread:117:5: note: candidate: std::thread::thread() 
    thread() noexcept = default; 
    ^~~~~~ 
/usr/local/Cellar/gcc/6.3.0_1/include/c++/6.3.0/thread:117:5: note: candidate expects 0 arguments, 4 provided 
mergesort.cpp:32:66: error: no matching function for call to 'std::thread::thread(<unresolved overloaded function type>, std::reference_wrapper<std::vector<int> >, int, int&)' 
     std::thread sort_thread2(mergesort, std::ref(v), m + 1, r); 
                   ^
In file included from mergesort.cpp:3:0: 
/usr/local/Cellar/gcc/6.3.0_1/include/c++/6.3.0/thread:128:7: note: candidate: template<class _Callable, class ... _Args> std::thread::thread(_Callable&&, _Args&& ...) 
     thread(_Callable&& __f, _Args&&... __args) 
     ^~~~~~ 
+0

Gibt es einen Grund 'v' mit einem Verweis auf wickeln, wenn es bereits eine Referenz? –

+0

[Kann nicht reproduziert werden] (http://coliru.stacked-crooked.com/a/a0841ea4da50c8dd). – nwp

+1

@MikelF Soweit ich weiß, erstellt der 'std :: thread' -Konstruktor Kopien aller übergebenen Argumente. Um Referenzen also korrekt zu behandeln, müssen Sie sie in 'std :: ref'-Funktionen einschließen, so dass' std :: thread' die Referenz "entpackt", wenn sie tatsächlich verwendet wird. – Xirema

Antwort

0

wechselnden Linien 31/32 bis:

std::thread sort_thread1([&v, l, m] { mergesort(v, l, m); }); 
    std::thread sort_thread2([&v, m, r] { mergesort(v, m + 1, r); }); 

wird es zu kompilieren bekommen.

Ich glaube nicht, es aber richtig ist:

Eingang:

5 4 3 2 1 0 

Ausgang

0 1 2 3 4 
+0

es funktioniert. Danke! aber ich will immer noch wissen warum – SXKDZ

0

Der Compiler sagte, es couldn't deduce template parameter '_Callable', so geben wir die überladene explizit Version.

die folgenden Änderungen

// ... 
typedef void (*mergesort_ptr_t)(std::vector<int> &v, int l, int r); 

void mergesort(std::vector<int> &v, int l, int r) { 
    if (l < r) { 
     int m = (l + r)/2; 
     std::thread sort_thread1((mergesort_ptr_t)(mergesort), std::ref(v), l, m); 
     std::thread sort_thread2((mergesort_ptr_t)(mergesort), std::ref(v), m + 1, r); 
// ... 

Arbeit scheint.

Compiler Informationen:

➜ Downloads g++ -std=c++11 sxkdzmtsort.cpp 
➜ Downloads g++ --version 
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/include/c++/4.2.1 
Apple LLVM version 8.0.0 (clang-800.0.42.1) 
Target: x86_64-apple-darwin15.6.0 
Thread model: posix 
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin