Gaming Life

一日24時間、ゲームは10時間

std::bindではデフォルト引数を省略できない

std::bindを使っていたらある問題に遭遇した。

void func(int a){
    std::cout << a * 10 << std::endl;
}
int main(){
    using namespace std::placeholders;
    auto fuction = std::bind(func, _1);
    function(2);
}

std::bindを使ってライブラリで用意されている関数を束縛し別のところで呼び出す、といったことをしたかったのだが、これが何故かコンパイルが通らなかった。(実際は、クラスのメンバ関数をbindした。簡単のためそのコードはここに示す

なぜだろうか……といろいろ調べて回ったところ、とても単純な話だった。

void func(int a, int b = 10){
    std::cout << a * b << std::endl;
}
int main(){
    using namespace std::placeholders;
    auto fuction = std::bind(func, _1);
    function(2);
}

引数1つで呼び出すものと思っていたfunc()関数が、実際は第2引数にintを取る関数で、それにデフォルト引数が設定されていた。じゃあどうやってこの関数を束縛すればいいかというと、bind時、デフォルト引数も明示的に渡せばよい。

// Error!
// auto function = std::bind(func, _1);

// OK!
auto function = std::bind(func, _1, 10);

// call
function(2);

wandbox.org

bindは使うべきではないという話

ここまでbindを使って関数を束縛してきたが、調べてみると、bindはパフォーマンス上に問題があるらしい。

じゃあ代わりに何を使うのかっていうと、みんな大好きラムダ式である。

// Error!
// auto function = std::bind(func, _1);

// OK! (low performance)
auto function = std::bind(func, _1, 10)

// OK! (high performance)
auto function = [=](int _1){ func(_1); };

// call
function(2);

Compiler Explorerbindラムダ式を比較してみると一目瞭然でパフォーマンスにかなり影響することがわかる。

まとめ

bindなんか使わずラムダを使おう。