OSDN Git Service

memberwise_swap を追加
authorSubaruG <subaru_g@users.sourceforge.jp>
Sun, 7 Feb 2010 09:07:51 +0000 (18:07 +0900)
committerSubaruG <subaru_g@users.sourceforge.jp>
Sun, 7 Feb 2010 09:07:51 +0000 (18:07 +0900)
gintenlib/memberwise_swap.hpp [new file with mode: 0644]
tests/memberwise_swap.cc [new file with mode: 0644]

diff --git a/gintenlib/memberwise_swap.hpp b/gintenlib/memberwise_swap.hpp
new file mode 100644 (file)
index 0000000..a418c6f
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef GINTENLIB_INCLUDED_MEMBERWISE_SWAP_HPP_
+#define GINTENLIB_INCLUDED_MEMBERWISE_SWAP_HPP_
+
+/*
+
+      <gintenlib/memberwise_swap.hpp>
+
+  memberwise_swap : メンバ変数の swap
+
+  宣言:
+    template< typename T, typename Args... >
+    void memberwise_swap( T& one, T& another, Args... mem_ptr... );
+
+  機能:
+    one.swap( another ); を呼び出す friend 関数 swap を定義します
+  
+*/
+
+#include <algorithm> // for std::swap
+
+#include <boost/preprocessor/arithmetic/inc.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_binary_params.hpp>
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+
+namespace gintenlib
+{
+  #define GINTENLIB_GEN_SWAP_( z, n, mp ) \
+    swap( one.*BOOST_PP_CAT( mp, n ), another.*BOOST_PP_CAT( mp, n ) );
+  
+  #define GINTENLIB_GEN_( z, n, unused_ )                       \
+    template<typename T, BOOST_PP_ENUM_PARAMS( n, typename M )> \
+    inline void memberwise_swap( T& one, T& another,            \
+      BOOST_PP_ENUM_BINARY_PARAMS( n, M, T::*mp ) )             \
+    {                                                           \
+      using std::swap;                                          \
+      BOOST_PP_REPEAT_FROM_TO( 0, n, GINTENLIB_GEN_SWAP_, mp )  \
+    }
+    // #define GINTENLIB_GEN_( z, n, unused_ )
+  
+  BOOST_PP_REPEAT_FROM_TO( 1, 10, GINTENLIB_GEN_, _ )
+  
+  #undef GINTENLIB_GEN_
+  #undef GINTENLIB_GEN_SWAP_
+
+} // namespace gintenlib
+
+#endif  // #ifndef GINTENLIB_INCLUDED_MEMBERWISE_SWAP_HPP_
diff --git a/tests/memberwise_swap.cc b/tests/memberwise_swap.cc
new file mode 100644 (file)
index 0000000..b8b8575
--- /dev/null
@@ -0,0 +1,56 @@
+#include "../gintenlib/memberwise_swap.hpp"
+
+// boost の単体テストフレームワーク
+#include <boost/test/minimal.hpp>
+
+#include <string>
+#include <boost/scoped_ptr.hpp>
+
+// 使用例(面倒なのでメンバ3個ので代表する)
+struct hoge
+{
+  // 内部データ構造体とか
+  struct data
+  {
+    explicit data( int x_ )
+      : x(x_){}
+    
+    int x;
+  };
+  
+  int i;                      // 組み込み型 
+  std::string s;              // assignable なクラス
+  boost::scoped_ptr<data> p;  // noncopyable かつ swappable なクラス
+  
+  hoge( int i_, const std::string& s_, int x )
+    : i( i_ ), s( s_ ), p( new data(x) ) {}
+  
+  // 本体
+  void swap( hoge& other )
+  {
+    // 交換したい2オブジェクトに続けて、メンバ変数へのポインタを並べる
+    gintenlib::memberwise_swap( *this, other, &hoge::i, &hoge::s, &hoge::p );
+  }
+  friend void swap( hoge& one, hoge& another )
+  {
+    one.swap( another );
+  }
+  
+};  // struct hoge
+
+// テスト本体
+int test_main( int, char** )
+{
+  hoge h1( 1, "foo", 23 ), h2( 2, "bar", 42 );
+  hoge::data *p1 = h1.p.get(), *p2 = h2.p.get();
+  
+  // swap 呼び出し
+  swap( h1, h2 );
+  
+  // 交換出来ているかチェック
+  BOOST_CHECK( h1.i == 2        && h2.i == 1        );
+  BOOST_CHECK( h1.s == "bar"    && h2.s == "foo"    );
+  BOOST_CHECK( h1.p.get() == p2 && h2.p.get() == p1 );
+  
+  return 0;
+}