2017-03-13 5 views
2

バグの原因を見つけるために掘り下げた後、私は次のものが合法的なC++ 11(GCC/Wall with Wallと一緒にコンパイルされている)と思われることに驚きました。特に、f1は、その引数を値で取って、RefFunctionに参照することができます。lvalue参照を取るstd ::関数にby-value引数を取る関数をバインドすることができますか?

私は説明のためにグーグルを試みましたが、関連するものは何も見つかりませんでした。なぜなら、私はグーグルを正確に知らないからです。私は本当になぜこれが合法であるかによって誰かが私を導くことができれば感謝しています。

#include <iostream> 

using namespace std; 

void f1(int val) { 
    val = 1; 
} 

void f2(int& val) { 
    val = 2; 
} 

using RefFunction = std::function<void(int&)>; 

int main() 
{ 
    using namespace std::placeholders; 
    int val = 42; 
    // I was expecting a compile error here telling me that f1 doesn't 
    // have the right signature (int instead of int&) 
    RefFunction f = f1; 
    f(val); 
    cout << val << endl; // prints 42 

    // This makes sense, f2 takes argument by reference 
    f = f2; 
    f(val); 
    cout << val << endl; // prints 2 
    return EXIT_SUCCESS; 
} 

答えて

5

当面standardeseをさておき、以下の観点から考える:

void f1(int val) { 
    val = 1; 
} 

void f2(int& val) { 
    val = 2; 
} 

void WrapperFunction(int& val) 
{ 
    f1(val); // Should be OK 
    f2(val); // Should be OK. 
} 

コンパイラは上記のコードに問題があってはなりません。 WrapperFunctionstd::functionと似ていると考えると、std::functionf1またはf2で構成されているかどうかにかかわらず、コンパイラは問題ありません。

4

std::functionのテンプレート引数はstd::functionを呼び出すことができる様子を強制します。 RefFunctionは、intの左辺値または暗黙的にタイプintの左辺値に変換できるものでのみ呼び出すことができます。次に、基底関数f1またはf2を呼び出します。 intへの参照を受け取る関数は、常にその参照を使用して、値によってintを受け取る関数を呼び出すことができます。参照されるintは単にコピーされます。一般std::function<R(T...)>

は、それがstd::functionの関数呼び出し演算子のT...パラメータは、実際に根本的な呼び出し可能を呼び出すために使用することができることが本当だとして任意の署名を使用して呼び出し可能に保存することができます。署名は正確に一致する必要はありません。

+0

ありがとうございます。これは今実際に意味をなさない。私は残念なことに1つの答えだけを受け入れることができ、私は両方の答えが良いと言うでしょう。 – Julien

関連する問題