C++11 の lambda expression を使用した名前付き初期化

のようなものです。
lambda expression 内で構造体を定義しているので、そのまま引数として渡すことが出来ます。
イメージとしては Boost.Parameter が近いかしら?

[ソース]

#include <iostream>
#include <string>
#include <boost/typeof/typeof.hpp>

#define _(MEMBERS)  []{ struct { MEMBERS; } local; return local;}()

template<typename T>
struct initializer{
    template<typename ...Args>
    T
    operator ()(Args... args) const{
        return T{ std::forward<Args>(args)... };
    }
};

template<typename T>
initializer<T>
local(T){
    return initializer<T>{};
}


template<typename T>
void
draw(T t){
    std::cout << "name:" << t.name << ", age:" << t.age << std::endl;
}

int
main(){
    // 名前を付けて構造体を定義して、関数に渡す
    draw(_(int age = 15; std::string name = "mami"));
    draw(_(std::string name = "homu"; int age = 14));
    
    // auto が使えないので BOOST_AUTO で定義とか
    draw(_(BOOST_AUTO(name, "mado"); BOOST_AUTO(age, 13)));

    // ローカル変数を渡す場合は local() でラップ
    std::string name = "saya";
    int age = 13;
    draw(local(_(std::string name; int age))(name, age));

    // ローカル変数として定義することも
    auto an = _(std::string name = "an"; int age = 14);
    draw(local(_(std::string name; int age))(an.name, an.age));

    return 0;
}

[出力]

name:mami, age:15
name:homu, age:14
name:mado, age:13
name:saya, age:13
name:an, age:14


こんな感じで lambda expression 内で構造体を定義しています。
型を定義しないとダメなのはちょっとカッコ悪いですが…。
値の初期化は Non-static data member initializers ですね。
初期化しないのであれば、msvc2010 でも使えるかな。
マクロの引数で構造体の中身を定義しているのでカンマではなくてセミコロン区切りなのに注意。
メソッドや型なんかも定義できそう。


あと lambda なので decltype と constexpr が使えないのがちょっと悲しいですね…。
個人的には関数側を変更する必要がないので結構いい感じなんですが、さて。

[コンパイラ]

  • g++ (GCC) 4.7.0 20111210 (experimental)