スレッドへの転送参照を渡すとの最初の具体的な機能を見てみましょう:ラッパークラスに
void boo1() { std::cout << "boo1\n"; }
void boo2 (std::string) { std::cout << "boo2\n"; }
struct X {
void boo3() { std::cout << "boo3\n"; }
void boo4 (std::string) { std::cout << "boo4\n"; }
};
私はそれらの関数が例外保護(以下の説明を)行い、いくつかの「ガード」機能、を実行することにしたいです。
template <typename C, typename... Args>
typename std::enable_if<!std::is_member_function_pointer<C>::value, void>::type
foo (C&& c, Args&&... args) {
std::cout << "not memfun\n";
c (std::forward<Args> (args)...);
}
template <typename C, typename T, typename... Args>
typename std::enable_if<std::is_member_function_pointer<C>::value, void>::type
foo (C&& c, T* o, Args&&... args) {
std::cout << "memfun\n";
(o->*c) (std::forward<Args> (args)...);
}
そして今、私は新しいスレッドでboo1()
、boo2()
、X::boo3()
とX::boo4()
を実行したいが、foo()
関数で使用される「保護」と:だから、私は2つの機能を無料機能用と他のメンバ関数のために書かれています。明示的std::join()
またはstd::detach()
の使用を停止し、さらに一歩、私が書かれているスレッドのラッパークラスを行く、だから、
X x;
std::thread th1 {&foo<void (*)()>, &boo1};
std::thread th2 {&foo<void (*) (std::string), std::string>, &boo2, "Hello"};
std::thread th3 {&foo<void (X::*)(), X>, &X::boo3, &x};
std::thread th4 {&foo<void (X::*) (std::string), X, std::string>, &X::boo4, &x, "Hello"};
:だから、何の問題もなく私はこれを行うことができます。 デストラクタが動作しているときにInstedが呼び出されます。この例の簡潔さのために、私はそれらのうちの1つだけを使用しました。 ので、コードは次のようになります。
class Th {
public:
template <typename C,
typename = typename std::enable_if<!std::is_member_function_pointer<C>::value, void>::type,
typename... Args>
Th (C&& c, Args... args) // (X)
: t {foo<C, Args...>, std::forward<C> (c), std::forward<Args> (args)...} {}
template <typename C,
typename = typename std::enable_if<std::is_member_function_pointer<C>::value, void>::type,
typename T,
typename... Args>
Th (C&& c, T* o, Args... args) // (Y)
: t { foo<C, T, Args...>, std::forward<C> (c), o, std::forward<Args> (args)...} {}
~Th() { t.join(); }
private:
std::thread t;
};
そして、この実装では問題、以下の使用例はありません。excepctedとして
X x;
Th h1 {&boo1};
Th h2 {&boo2, "Hello"};
Th h3 {&X::boo3, &x};
Th h4 {&X::boo4, &x, "Hello"};
は仕事が。しかし、ここには一つの欠陥があります - 完全な転送はありません。私が望まれるArgs&&...
に(X)
と(Y)
Args...
に変更した場合は、 コードはいくつかのエラーでコンパイルできない、そのうちの一つは、次のとおりです。std::thread
コンストラクタで行うことができない、私はそれを正しく理解すれば
error: no type named ‘type’ in ‘class std::result_of<void (*(void (*)(std::basic_string<char>), const char*))(void (*&&)(std::basic_string<char>), const char (&)[6])>’
、std::bind()
それは仕事です、または私が間違っている場合は私を修正します。
私の質問はこの場合、完璧な転送を利用するにはどうすればよいですか?
これをコンパイルするために使用されたコンパイラはGCC 4.8.1でした。
約束の説明:私はtry
とcatch
とc()
への呼び出しを囲むfoo()
関数は例外がロギングメカニズムのいくつかの種類では、プロセスの情報をcatchedされていることを確認し、透明性を必要に応じて例外を再スローしたいですTh
クラスのユーザーに送信します。
興味深い。これは、 'h2'と' h4'の '' Hello "'ではなく 'std :: string(" Hello ")'で実行するとコンパイルに失敗します。このエラーは、第1引数auto forward_to_thread(T && t) '(' clang 5.0')に対して 'std :: __ cxx11 :: basic_string'から 'std :: __ cxx11 :: basic_string &&'への 'no known conversion from' –
cantordust
'forward_to_thread'の引数も転送され、固定されるべきです。ありがとう。 – krzaq
これはクールです、ありがとう –