たぶん既にあるネタと思いますが、せっかくソースコード書いたので掲載します。
C++で本格的にプログラムを書く場合、ほとんど全てのクラスに swap 関数を実装することになります。
これは例外安全の要求(詳しくは Exceptional C++ を参照)もありますし、単純に、効率的な swap があれば様々なアルゴリズムの記述に便利、という側面もあります。
実際問題として、コピーは出来ないけど swap はできる、というクラスは非常に多く、そういったクラスでも擬似的に代入に近い動作を行える swap は、非常に重宝するわけですが、ここで問題があります。
swap 関数の実装って、長いソースコードではないにしろ、少し面倒じゃないですか?
struct hoge { member1 mem1; member2 mem2; // and so on // nothrow swap void swap( hoge& other ) { using std::swap(); swap( mem1, other.mem1 ); swap( mem2, other.mem2 ); // and so on. } friend void swap( hoge& one, hoge& another ){ one.swap(another); } };
こうやって各メンバごとに決まり文句を並べていくだけだから楽、と言えなくもないですが、もう少し記述量を減らすことができてもバチは当たらない筈です。
まぁ実際問題として記述量を減らす必要もあんまりないですが、一応そういうのもできるよ、って感じで試しに作ってみるのも、まあ悪くないでしょう。
というわけで、実際に作ってみました: http://codepad.org/N7oEMKJT
#include <algorithm> // for std::swap #include <boost/preprocessor.hpp> #define GEN_SWAP_( z, n, d ) \ swap( one.*BOOST_PP_CAT(m, n), another.*BOOST_PP_CAT(m, n) ); #define GEN_( z, n, d ) \ template<typename T, BOOST_PP_ENUM_PARAMS( n, typename M )> \ void memberwize_swap( T& one, T& another, \ BOOST_PP_ENUM_BINARY_PARAMS( n, M, m ) ) \ { \ using std::swap; \ BOOST_PP_REPEAT_FROM_TO( 0, n, GEN_SWAP_, _ ) \ } BOOST_PP_REPEAT_FROM_TO( 1, 10, GEN_, _ ) #undef GEN_ #undef GEN_SWAP_
使い方:
struct hoge { int i, j; hoge( int i_, int j_ ) : i(i_), j(j_) {} void swap( hoge& other ) { // 対象オブジェクトに加え swap する全てのメンバ変数へのポインタを渡す memberwize_swap( *this, other, &hoge::i, &hoge::j ); } friend void swap( hoge& one, hoge& another ) { one.swap(another); } };
以上。メンバ変数の数が多くなってくると、一気に楽になるはずです。
ちなみにメンバ変数へのポインタを使ってるけど、最適化を有効にすれば全く普通の swap と同等の処理に展開してくれるので、コストを気にする場合も安心ですよっと。