Boost.Initialized で、宣言時に初期値を設定する
Boost.Initialized といいつつ、ほぼオレオレ Initialized になっていますが……。
Boost.Initialized は初期化のみで、初期値を設定することが出来ないので出来るようにしてみました。
基本的な動作は、Boost.Initialized と同じです。
[サンプルソース]
#include <iostream> #include <string> #include <boost/mpl/divides.hpp> template<typename T, typename Initializer = void> struct initialized; namespace mpl = boost::mpl; template<typename T1, typename T2> struct divides : mpl::divides<T1, T2>{ template<typename T> operator T() const{ return static_cast<T>(static_cast<T>(T1::value) / static_cast<T>(T2::value)); } }; typedef divides<mpl::int_<355>, mpl::int_<113> > PI; // 355/113 で PI の近似値 // 実行時に計算したくなければこんな感じ。 // struct PI{ // operator float() const{ // return 3.14f; // } // }; template<typename Seq> struct c_str : mpl::c_str<Seq>{ typedef typename Seq::value_type const* value_type; operator value_type() const{ return mpl::c_str<Seq>::value; }; }; struct init_hello_world{ typedef std::string value_type; operator value_type() const{ return "hello world"; } }; struct check{ initialized<int> value1; // int initialized<mpl::int_<10> > value2; // 10 で初期化 initialized<mpl::true_> value3; // 型がなくても OK initialized<float, PI> value4; // 実数も渡せる initialized<init_hello_world> value5; // ユーザ側で定義した値で初期化 initialized< // MPL.String で文字列型も初期化 std::string, c_str<mpl::string<'piyo'> > > value6; }; int main(){ check c; std::cout << c.value1 << std::endl; std::cout << c.value2 << std::endl; std::cout << c.value3 << std::endl; std::cout << c.value4 << std::endl; std::cout << c.value5.data() << std::endl; std::cout << c.value6.data() << std::endl; return 0; }
[出力]
0 10 1 3.14159 hello world piyo
変数宣言をする際に Initializer を渡すことで、Initializer に定義されている設定で初期化を行います。
Initializer がなければ、Boost.Initialized と同様にデフォルト値で初期化が行われます。
Initializer は、T型へのキャストが書かれていればなんでもいいです。
value_type が定義されているならば T に直接 Initializer を渡してしまっても構いません。
Boost.MPL の Integral Constant をそのまま初期値として設定できます。
string も MPL.String を使用しようして初期化を行うことが出来ます。
って、感じで、とりあえず、つくってみました。
Boost.Initialized 全然使わないのにねー……。
あと C++0x はガン無視。
constexpr の辺りと組み合わせるとどうなんでしょうか。
[boost]
ver 1.46.1
[参照]
http://www.boost.org/doc/libs/1_46_1/libs/mpl/doc/refmanual/integral-constant.html
全てのソースはイカ。
#include <boost/utility/value_init.hpp> #include <boost/utility/enable_if.hpp> #include <boost/mpl/has_xxx.hpp> namespace detail{ namespace mpl = boost::mpl; template<typename T, typename Initializer, typename sfinae = void> struct initialized_impl : boost::initialized<T>{ typedef boost::initialized<T> base_type; initialized_impl() : base_type(){} explicit initialized_impl(T const& arg) : base_type(arg){} }; // Initializer が void 以外の場合 template<typename T, typename Initializer> struct initialized_impl<T, Initializer, typename boost::disable_if< boost::is_void<Initializer> >::type > : boost::initialized<T>{ typedef boost::initialized<T> base_type; initialized_impl() : base_type(static_cast<T>(Initializer())){} explicit initialized_impl(T const& arg) : base_type(arg){} }; BOOST_MPL_HAS_XXX_TRAIT_DEF(value_type); // T::value_type があり、Initializer が void の場合 template<typename T> struct initialized_impl<T, void, typename boost::enable_if<has_value_type<T> >::type > : boost::initialized<typename T::value_type>{ typedef boost::initialized<typename T::value_type> base_type; initialized_impl() : base_type(static_cast<typename T::value_type>(T())){} explicit initialized_impl(T const& arg) : base_type(arg){} }; } // namespace detail template<typename T, typename Initializer = void> struct initialized : detail::initialized_impl<T, Initializer>{ typedef detail::initialized_impl<T, Initializer> base_type; initialized() : base_type(){} explicit initialized(T const& arg) : base_type(arg){} }; #include <iostream> #include <string> #include <boost/mpl/divides.hpp> #include <boost/mpl/string.hpp> namespace mpl = boost::mpl; template<typename T1, typename T2> struct divides : mpl::divides<T1, T2>{ template<typename T> operator T() const{ return static_cast<T>(static_cast<T>(T1::value) / static_cast<T>(T2::value)); } }; typedef divides<mpl::int_<355>, mpl::int_<113> > PI; // struct PI{ // operator float() const{ // return 3.14f; // } // }; template<typename Seq> struct c_str : mpl::c_str<Seq>{ typedef typename Seq::value_type const* value_type; operator value_type() const{ return mpl::c_str<Seq>::value; }; }; struct init_hello_world{ typedef std::string value_type; operator value_type() const{ return "hello world"; } }; struct check{ initialized<int> value1; initialized<mpl::int_<10> > value2; initialized<mpl::true_> value3; initialized<float, PI> value4; initialized<init_hello_world> value5; initialized< std::string, c_str<mpl::string<'piyo'> > > value6; }; int main(){ check c; std::cout << c.value1 << std::endl; std::cout << c.value2 << std::endl; std::cout << c.value3 << std::endl; std::cout << c.value4 << std::endl; std::cout << c.value5.data() << std::endl; std::cout << c.value6.data() << std::endl; return 0; }