C++0x の Perfect Forward は,便利なのですが,イチイチ変数の型名を指定しなきゃいけないのが面倒です:
#include <utility> template< class T, class U > auto add( T && x, U && y ) -> decltype( std::forward<T>(x) + std::forward<U>(y) ) { return std::forward<T>(x) + std::forward<U>(y); }
もちろん,これには深い理由があるわけですが,でも手動で指定するのは面倒ですし,ミスの元.
というわけで,型指定を自動で行ってくれるマクロを,適当に書いてみました:
// 定義 #include <utility> #define STD_FORWARD(x) std::forward<decltype(x)>(x) // 使い方 template< class T, class U > auto add( T && x, U && y ) -> decltype( STD_FORWARD(x) + STD_FORWARD(y) ) { return STD_FORWARD(x) + STD_FORWARD(y); }
https://github.com/gintenlabo/pezzi/blob/master/forward.cc
Variadic Templates でも,きちんと動作します:
// 例として http://d.hatena.ne.jp/gintenlabo/20110628/1309221610 の make_unique_lock を template< class Mutex, class... Args > inline std::unique_lock<Mutex> make_unique_lock( Mutex& m, Args&&... args ) { return std::unique_lock<Mutex>( m, STD_FORWARD(args)... ); }
また,引数が値渡しや const&
であっても,問題ありません.
通常の Perfect Forward と同様に,値渡しの場合は move され,参照渡しの場合にはそのまま渡されます.((とはいえ,その場合は std::move
を使うか,そのまま渡すべきでしょう.))
また,ローカル変数に対して適用することもでき,その場合,そのローカル変数が値なら move され,参照なら適切に forward されます:
int main() { std::string s = "hoge"; { std::string t = s; some_function( STD_FORWARD(t) ); // 変数 t はこれ以上使わないので, move してよい } { std::string& r = s; some_function( STD_FORWARD(r) ); // 変数 r 自身はこれ以上使わないが,参照なので move してはいけない } { std::string&& r = std::move(s); // s を move しているので,これ以降 s を使ってはいけない some_function( STD_FORWARD(r) ); // r は参照だが,参照先の s が既に move されてるので, move してよい } }
と,なんとなく便利そうに見えますが,あくまでマクロなので,普通は使わないほうがいいと思います.