2012-05-23 3 views
16

はどうすればデフォルト引数を指定せず、デフォルトの引数を取る関数に結合し、その後、引数なしで呼び出すことができますか?デフォルトの引数をとり、それを呼び出す関数にバインドできますか?

void foo(int a, int b = 23) { 
    std::cout << a << " " << b << std::endl; 
} 

int main() { 
    auto f = std::bind(foo, 23, 34); // works 
    f(); 


    auto g = std::bind(foo, 23); // doesn't work 
    g(); 

    using std::placeholders::_1; 
    auto h = std::bind(foo, 23, _1); // doesn't work either 
    h(); 

} 
+1

「動作しない」を定義します。変数に異なる名前を付けた場合、コードはコンパイルされます。 –

+0

なぜfに再割り当てしていますか? – 111111

+0

@ R.MartinhoFernandesええ、申し訳ありませんが、例は不完全でした。更新されたコード – inf

答えて

20

基本的には、いつでもあなたがfoo(x)を書くコンパイラはfoo(x, 23);にそれを変換します。実際に関数名を直接呼び出している場合にのみ機能します。関数のシグネチャは、void(int, int)あるので、あなたは」tは、例えば、void(*)(int)&fooを割り当てることができます。デフォルトのパラメータは、署名に含まれません。変数をvoid(*)(int, int)変数に代入すると、デフォルトパラメータに関する情報が失われます。その変数のデフォルトパラメータを利用することはできません。 std::bindは、その腸のどこかにvoid(*)(int, int)を格納しており、デフォルトのパラメータ情報を失います。

あり機能外部からのパラメータのデフォルト値を取得するためのC++での方法はないので、あなたは、あなたがバインドすると、手動でデフォルト値を提供して立ち往生しています。

+0

素晴らしい背景、ありがとう。 – inf

8

私はあなたがラムダを使用したい動作をシミュレートできると思います。

本の線に沿って何か:

auto g = [](){ foo(23); }; 

EDIT:ちょうどチェックし、正常に動作するようです:http://ideone.com/SPSvi

0

私は2つのソリューションを持っている:

1 - あなたは(FOOをオーバーロードすることができます)、デフォルトでオリジナルを呼び出してもらう:

void foo(int a, int b) 
{ 
    std::cout << a << " " << b << std::endl; 
} 

inline void foo(int a) 
{ 
    foo(a, 23); 
} 

2 - あなたがデフォルトとして静的変数を使用して、バインディングプロセスでそれを使用することができます:R.マルティーニ・フェルナンデス答えを

static int foo_default_b = 23; 
void foo(int a, int b = foo_default_b) 
{ 
    std::cout << a << " " << b << std::endl; 
} 

auto g = std::bind(foo, 23, foo_default_b); 
g(); 
0

This answerが不一致。あなたは確かにあなただけのようにプレースホルダを配置する必要があり、デフォルトパラメータにバインドするboost::bindを使用することができます。

boost::bind<void (int, int)>(foo, _1, _2)(12); 

予想通りこれは、foo(12, 23)を呼び出します。私はこの特定のコードをテストしませんでしたが、上にリンクされた答えに基づいて私のコードで何か似たことをしました。それはgcc 4.8.5で動作します。

うーん、私はちょうどこれを約std::bind、ないboost::bindを求めていることに気づきました。私は違いがあるかどうかは分かりません。

関連する問題