2017-01-24 13 views
0

MacOSで次のコードを試してコンパイルエラーが発生しました。私の質問は、スレッドを作成するときに関数に引数を渡す最善の方法は何ですか?C++ 11マルチスレッドマージソート

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

私はここ++打ち鳴らすとgを試してみましたが、次のように同じエラーを取得します。

~/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

は、それがすでに基準となる基準で 'v'をラップする理由はありますか? –

+0

[再生できません](http://coliru.stacked-crooked.com/a/a0841ea4da50c8dd)。 – nwp

+1

@MikelF私が知る限り、 'std :: thread'コンストラクタは渡されたすべての引数のコピーを作成します。参照を正しく扱うためには、 'std :: thread'が参照を実際に使用するときに参照を「アンパック」するように、それらを' std :: ref'関数でラップする必要があります。 – Xirema

答えて

0

をするライン31/32の変更:

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

はそれをコンパイルするために取得します。

私はそれが正しいだとは思わない:

入力:

5 4 3 2 1 0 

出力

0 1 2 3 4 
+0

です。どうも!しかし、私はまだ理由を知りたい – SXKDZ

0

コンパイラはcouldn't deduce template parameter '_Callable'を言ったので、私たちは、明示的にオーバーロードされたバージョンを指定します。

以下は

// ... 
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); 
// ... 

を変更するには、仕事です。

コンパイラ情報:

➜ 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