しるふぃずむ

どうもプログラマです。好きなものはC#とジンギスカンです。嫌いなものはJava。プログラムおもちろいね。

lvalue/rvalueに応じて挙動を変える

range adaptorを作ろうとしてるときに考えていたのが発端.
与えたrangeから何かしら別のrangeを作って返すようなことがしたい時,既に存在するrangeを渡すこともあればboost::irangeなんかで作ったrvalue refなrangeを渡したくなることもあります.
パラメータがlvalueならそのまま参照を持ち,rvalueであればmoveしてキャプチャしてしまうような挙動が望ましいと思ったのですが今ひとつ実装が浮かばず放っておいたのですがそれっぽいのができました.
全体はこれ=>Ideone.com - ELarMP - Online C++0x Compiler & Debugging Tool
こんな感じにしてやるとlvalueを渡せばlvalue ref, rvalueを渡せばmoveしてlvalueで持ちます.
moveのし忘れが無ければオブジェクトの寿命が切れてしまってどうしようもないというのはなんとかできそうですかね.

template<typename...Args>
struct Foo
{
        Foo(Args&&... args)
                : t_(std::forward<Args>(args)...)
        { }

        ...

        std::tuple<Args...> t_;
};

// lvalue refならlvelue refのまま扱う
template<typename...Args>
auto foo(Args&... args)
        -> Foo<Args&...>
{
        return Foo<Args&...>{args...};
}
// rvalue refならmoveする
template<typename...Args>
auto foo(Args&&... args)
        -> Foo<Args...>
{
        return Foo<Args...>{std::forward<Args>(args)...};
}

std::forwardさん素敵.
ついでにVariadic Templateでメタメタしたコードを個別に書くのに疲れたのでboost::fusionの練習.