2017-05-18 3 views
2

次のシナリオを検討:C++ - コンパイルはSTDにオーバーロードされた関数を呼び出すに失敗する::スレッド

// utils.h

// utils.cpp

#include "utils.h" 

void Utils::do_something(int a, std::list<int> *b) { 

} 

void Utils::do_something(int a, std::list<std::string> *b) { 

} 

// main.cpp

私が間違ってやっている

error: no matching function for call to 'std::thread::thread(<unresolved overloaded function type>, int, std::list<int>*)' 

任意のアイデア:私はそれをコンパイルすると

#include <thread> 
#include <list> 
#include "utils.h" 

int main() { 
    std::list<int> list; 
    std::thread t(Utils::do_something, 17, &list); 
    t.join(); 
    return 0; 
} 

、私は次のエラーを取得しますか? std::list<std::string>*を取得するオーバーロード関数を追加する前に、コンパイルがうまくいっていました。

+1

2つの 'Utils :: do_something'関数は(おおよそ)同じことをしていますか?そうでない場合は、異なる(より記述的な)関数名を使用して解決します。 –

+1

これは私があなたに完全に同意する明白な解決策です。しかし、スレッドが多重定義された関数を受け取ることができないという文書化された問題はありますか? – SomethingSomething

+1

コンパイラが残りのパラメータの型だけに基づいて最初のパラメータの正しいオーバーロードを推測できると期待するのは少し難しいと思われますが、誰かが標準から引用できます(またはすることができます)。興味深い質問。 –

答えて

4

ここでの問題は、あなたがそれはそれらがそれに渡された関数を試してみて、決定するために使用されていないstd::threadにパラメータを渡すにもかかわらず、である...オーバーロードを明確にするためにstatic_castを使用することができます。関数の型を分離して解決しようとします。そうすると、2つの異なるバージョンがあるので、どちらが必要かわからないので停止します。

残念ながら、使用する関数をコンパイラに伝える必要があります。あなたは、あなたが望む特定の関数ポインタに関数をキャストすることによってそれを行うことができます。

の代わりにあなたが

std::thread t([](auto first, auto second){ return Utils::do_something(first, second); }, 17, &list); 

のようにオーバーロードの解決は、通常の関数呼び出しで行わできるようにすることで、これは簡単にするためにラムダを使用することができますが、あなただけのキャプチャとしてこれもメンバ関数でうまく動作することをやってラムダのキャプチャリストで関数を呼び出すオブジェクト。これにより、オブジェクトをstd::threadに渡すか、std::bindを使用する必要がなくなります。

+0

よく使用する関数を指定していません。自動オーバーロード解決が遅れて、提供されたパラメータを使用できるようになりました。 – Quentin

+1

@Quentin言語を更新しました。ありがとう。 – NathanOliver

3

あなたは

std::thread t(static_cast<void(*)(int, std::list<int> *)>(&Utils::do_something), 17, &list); 
+0

ありがとうございます。実際に署名を手動で指定する必要がある場合は、関数の名前を「明白な解決策」にすることを好みます。問題は何か他に何かがあるかどうかです。 – SomethingSomething

関連する問題