非 const 参照を引数として渡すことは不可能であることに気付きましたstd::async
。
#include <functional>
#include <future>
void foo(int& value) {}
int main() {
int value = 23;
std::async(foo, value);
}
私のコンパイラ (GCC 4.8.1) では、この例に対して次のエラーが発生します。
error: no type named ‘type’ in ‘class std::result_of<void (*(int))(int&)>’
std::async
しかし、に渡された値を でラップするとstd::reference_wrapper
、すべて正常になります。 これは、 が引数を値で受け取るためだと思いますstd::async
が、エラーの理由はまだわかりません。
ベストアンサー1
これは意図的な設計上の選択/トレードオフです。
async
まず、渡された functionoidが引数を参照によって受け取るかどうかを必ずしも確認できるわけではありません。(単純な関数ではなく関数オブジェクトの場合は、たとえば、オーバーロードされた関数呼び出し演算子がある可能性があります。)async
したがって、「ターゲット関数が何を求めているかを確認すれば、適切な処理が実行されます」とは言えません。
設計上の問題は、すべての引数を可能な限り参照で受け取るか(つまり左辺値の場合)、または常にコピーを作成するかです。コピーを作成するのは安全ここでの選択: コピーはぶら下がることはできず、コピーは競合状態を示すこともできません (非常に奇妙な場合を除く)。そのため、すべての引数がデフォルトでコピーされるという選択が行われました。
しかし、その後、このメカニズムは、実際には非定数 lvalue 参照パラメータに引数を渡さないように記述されています。これは安全性のためのもう 1 つの選択肢です。そうしないと、元の lvalue を変更するはずの関数が、代わりにコピーを変更してしまい、追跡が非常に困難なバグが発生します。
しかし、本当に非定数 lvalue 参照パラメータが必要な場合はどうでしょうか。ぶら下がり参照と競合状態に注意することを約束するとしたらどうでしょうか。それが目的ですstd::ref
。これは危険な参照セマンティクスへの明示的なオプトインです。これは、「ここで何をしているか分かっている」ということを示す方法です。