宣言:
template< typename T >
+ struct storage_of
+ {
+ typedef boost::aligned_storage< sizeof(T), boost::alignment_of<T>::value >::type type;
+ };
+
+ template<typename T>
struct storage
- : boost::aligned_storage< sizeof(T), boost::alignment_of<T>::value > {};
+ {
+ // noncopyable にしてる都合上、必要
+ storage() {}
+
+ // メタ関数
+ // 内部に格納されてるストレージの型
+ typedef typename storage_of<T>::type storage_type;
+ // メタ関数としても使えるように(互換性の為)。
+ typedef storage_type type;
+
+ // アドレス取得
+ void* address();
+ void const* address() const;
+
+ private:
+ // noncopyable
+ storage( storage const& );
+ storage& operator=( storage const& );
+
+ };
機能:
T 型のクラスを格納できるだけのメモリ領域を確保したい場合、
namespace gintenlib
{
+ // storage_of<T>::type は T 型を格納できる POD 型
+ template<typename T>
+ struct storage_of
+ {
+ typedef typename boost::aligned_storage<
+ sizeof(T), boost::alignment_of<T>::value >::type type;
+ };
+
// T 型を収められるメモリ領域
+ // noncopyable で has_trivial_destructor
+ // boost::noncopyable を継承すると has_trivial_destructor にならないので
+ // 自前で代入とコピーを殺している
template<typename T>
struct storage
- : boost::aligned_storage< sizeof(T), boost::alignment_of<T>::value > {};
+ {
+ // noncopyable にしてる都合上、必要
+ // = default 指定が欲しい。
+ storage() {}
+
+ // メタ関数
+ // 内部に格納されてるストレージの型
+ typedef typename storage_of<T>::type storage_type;
+ // メタ関数としても使えるように(互換性の為)。
+ typedef storage_type type;
+
+ // アドレス取得
+ void* address() { return &data_; }
+ void const* address() const { return &data_; }
+
+ private:
+ storage_type data_;
+
+ // noncopyable
+ storage( storage const& );
+ storage& operator=( storage const& );
+
+ };
} // namespace gintenlib
--- /dev/null
+#include "../gintenlib/ptr_fun.hpp"
+
+// boost の単体テストフレームワーク
+#include <boost/test/minimal.hpp>
+
+#include <boost/format.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+
+// テスト関数1
+// 任意の引数をカンマ区切りで文字列化する
+struct functor1
+ : private boost::noncopyable
+{
+ typedef std::string result_type;
+
+ template<typename Arg1>
+ result_type operator()( const Arg1& arg1 )
+ {
+ return ( boost::format("%1%") % arg1 ).str();
+ }
+ template<typename Arg1, typename Arg2>
+ result_type operator()( const Arg1& arg1, const Arg2& arg2 )
+ {
+ return ( boost::format("%1%, %2%") % arg1 % arg2 ).str();
+ }
+};
+
+void test1()
+{
+ boost::shared_ptr<functor1> p = boost::make_shared<functor1>();
+ gintenlib::indirect_function< boost::shared_ptr<functor1> > f = gintenlib::ptr_fun(p);
+
+ BOOST_CHECK( f.get_pointer() == p );
+ BOOST_CHECK( &f.get_function() == p.get() );
+
+ BOOST_CHECK( f(1) == "1" );
+ BOOST_CHECK( f(1, "hoge") == "1, hoge" );
+}
+
+// テスト関数2(result_type なし)
+struct functor2
+ : private boost::noncopyable
+{
+ template<typename T>
+ T operator()( T x )
+ {
+ return ++x;
+ }
+};
+
+void test2()
+{
+ boost::shared_ptr<functor2> p = boost::make_shared<functor2>();
+ gintenlib::indirect_function< boost::shared_ptr<functor2>, int > f(p);
+
+ BOOST_CHECK( f.get_pointer() == p );
+ BOOST_CHECK( &f.get_function() == p.get() );
+
+ BOOST_CHECK( f(1) == 2 );
+}
+
+
+// テスト本体
+int test_main( int, char** )
+{
+ test1();
+
+ return 0;
+}
--- /dev/null
+// ヘッダ
+#include "../gintenlib/storage.hpp"
+
+// boost の単体テストフレームワーク
+#include <boost/test/minimal.hpp>
+
+#include <boost/type_traits.hpp>
+
+// テスト
+template<typename T>
+void test()
+{
+ // 型定義
+ typedef gintenlib::storage<T> storage_type;
+ typedef typename gintenlib::storage_of<T>::type raw_storage;
+
+ // 型審査
+ BOOST_CHECK(( boost::is_same<typename storage_type::storage_type, raw_storage>::value ));
+
+ // raw storage に対して
+ BOOST_CHECK(( sizeof( raw_storage ) == sizeof( T ) ));
+ BOOST_CHECK(( boost::is_pod<raw_storage>::value ));
+
+ // storage に対して
+ BOOST_CHECK(( sizeof( storage_type ) == sizeof( T ) ));
+ BOOST_CHECK(( boost::has_trivial_destructor<storage_type>::value ));
+
+ // アドレスのチェック
+ storage_type x;
+ BOOST_CHECK(( &x == x.address() ));
+}
+
+// 対象のクラス群
+struct empty_class {};
+
+struct virtual_class
+{
+ virtual ~virtual_class() {}
+ int member;
+};
+
+int test_main( int, char** )
+{
+ test<int>();
+ test<int const>();
+ test<int*>();
+ test<empty_class>();
+ test<virtual_class>();
+
+ return 0;
+}
+