閑古鳥

オールドプログラマの日記。プログラミングとか病気(透析)の話とか。

メソッドチェーンを使用した名前付き引数の実装

メソッドチェーンというのは、関数の戻り値としてオブジェクトを返すようにして、その戻り値のオブジェクトのメンバ関数を直接呼んで関数呼び出しを繋げていく様なコードの書き方を指します。のですかね? ……ちょっとその辺はよくわからないのですが、ともあれそのメソッドチェーンを利用して名前付き引数を実装してみます。

名前付き引数はその名の通り、関数呼び出しを行う際に引数を名前を指定して渡せる仕組みで、これがあると引数の順番だとかを気にしなくて良くなるので幸せになれるとかなれないとか。順番を忘れることはできるけど、名前を覚えなきゃいけないんで楽にはならないんじゃないかと思ったけれどそこで止めてしまうと終わってしまうので、その辺は無視します。まあ必要ない引数を省略できるのは良いかもしれません。

名前付き引数を C++ で実装するには、まず関数の唯一の引数として使用する構造体を定義します。そして、実際引数として欲しい変数をその構造体のメンバとして定義します。ここまではよくあると思うのですが、ここではさらにこの構造体に *this を返す Setter を定義してやります。

struct argument {
    std::string name_;
    int age_;

    argument() : name_("No Name"), age_(1) {}
    argument& setName(std::string const& name) {
        name_ = name; return *this;
    }
    argument& setAge(int age) {
        age_ = age; return *this;
    }
};

void f(argument const& a = argument())
{
    cout << "Name: " << a.name_ << endl;
    cout << "Age: " << a.age_ << endl;
}

int main()
{
    f(argument().setName("vader").setAge(0x15));
    f();
    return 0;
}

といった感じ。 setHoge 関数を繋げていく事で必要な引数だけを選んで渡すことができます。

構造体にコンストラクタを用意しておくことで引数を省略しても動作するようにすることができます。絶対に省略してはいけない引数がある場合はコンストラクタの引数として受け渡しを行えば良いでしょう。

いろいろ面倒なので実際使うかといえば使うことはないでしょうけれど、まあお遊び的なものとして。

関連: What is the "Named Parameter Idiom"? - C++ FAQ Lite