c_array つくった。
すでに誰得感が漂っていますが……。
[ソース]
#include <boost/mpl/vector.hpp> #include <boost/mpl/vector_c.hpp> #include <boost/mpl/range_c.hpp> #include <boost/range/algorithm/for_each.hpp> #include <boost/range/algorithm/equal.hpp> #include <boost/lambda/lambda.hpp> #include <boost/assert.hpp> #include <boost/range/irange.hpp> #include <vector> #include <iostream> namespace mpl = boost::mpl; template<typename Seq, typename ArrayType = array_type<mpl::_1, mpl::_2> > struct c_array; int main(){ boost::array<int, 4> v = {10, 3, 5, 2}; BOOST_ASSERT(boost::equal( v, c_array<mpl::vector_c<int, 10, 3, 5, 2> >::value )); boost::for_each( c_array<mpl::range_c<int, 0, 5> >::value, std::cout << boost::lambda::_1 << "," ); std::cout << std::endl; std::vector<int> v2 = c_array<mpl::range_c<int, -5, 5>, std::vector<mpl::_1> >::value; boost::for_each( v2, std::cout << boost::lambda::_1 << "," ); return 0; }
[出力]
0,1,2,3,4, -5,-4,-3,-2,-1,0,1,2,3,4,
mpl::c_str の Constant Sequence 版?
mpl::vector_c とかを Boost.Array とかに変換します。
boost::array<int, 4> v = c_array<mpl::vector_c<int, 10, 3, 5, 2> >::value; BOOST_ASSERT(boost::equal( v, c_array<mpl::vector_c<int, 10, 3, 5, 2> >::value ));
c_array と、いいつつ、デフォルトでは、 Boost.Array を使っているので、cpp_array に変えるべきか否か。
生配列は Boost.Array で、こんがり焼きましょう。
また、第二引数に、value_type を渡すことも出来ます。
std::vector を使用するならこんな感じ。
std::vector<int> v2 = c_array<mpl::range_c<int, -5, 5>, std::vector<mpl::_1> >::value; BOOST_ASSERT(boost::range::equal( v2, boost::irange(-5, 5) ));
mpl::_1 には配列の型が、mpl::_2 には、配列のサイズが渡されます。
配列の初期化は、Boost.Assign を使っています。
一応、BOOST_NO_INITIALIZER_LISTS で、切り替えているので、initializer_list が実装されている場合は、
value = { boost::mpl::at_c<Seq, 0>::type::value, boost::mpl::at_c<Seq, 1>::type::value, boost::mpl::at_c<Seq, 2>::type::value, ... };
な感じで、初期化を行っています。
手元に initializer_list を実装した環境がないので試していませんが……。
あと以前作った、オレオレ Initialized を使えば、クラス内の変数で初期化を行うことが出来ます。
struct hoge{ typedef c_array<mpl::range_c<int, -5, 5>, std::vector<mpl::_1> > init_array; std::vector<int> const& array() const{ return array_; } private: initialized< init_array > array_; // std::vector<int> array_; }; hoge h; BOOST_ASSERT(boost::equal( h.array(), boost::irange(-5, 5) ));
やったね!
[boost]
- ver 1.46.1
実装は以下から。
#include <boost/mpl/size.hpp> #include <boost/mpl/identity.hpp> #include <boost/mpl/apply.hpp> #include <boost/mpl/at.hpp> #include <boost/array.hpp> #include <boost/preprocessor/repeat_from_to.hpp> #include <boost/preprocessor/repetition/enum.hpp> #ifndef C_ARRAY_LIMIT_SIZE # define C_ARRAY_LIMIT_SIZE 100 #endif #if defined BOOST_NO_INITIALIZER_LISTS // initializer_list が実装されていない場合は、Boost.Assign を使用して、初期化を行う #include <boost/assign.hpp> #define PP_C_ARRAY_AC_C(z, n, text) \ (boost::mpl::at_c<Seq, n>::type::value) #define PP_C_ARRYA_AC_C_INITIALIZER(n) \ boost::assign::list_of BOOST_PP_REPEAT_FROM_TO(0, n, PP_C_ARRAY_AC_C, _) #else // initializer_list が実装されている場合は、initializer_list を使用する #define PP_C_ARRAY_AC_C(z, n, text) \ boost::mpl::at_c<Seq, n>::type::value #define PP_C_ARRYA_AC_C_INITIALIZER(n) \ { BOOST_PP_ENUM(n, PP_C_ARRAY_AC_C, _) } #endif namespace detail{ template<typename T, typename Size> struct array_type : boost::mpl::identity<boost::array<T, Size::value> >{}; template< typename Seq, long Size, typename ArrayType > struct c_array_impl; #define PP_C_ARRAY(z, n, text) \ template< \ typename Seq, \ typename ArrayType \ > \ struct c_array_impl<Seq, n, ArrayType>{ \ typedef c_array_impl<Seq, n, ArrayType> type; \ \ typedef typename boost::mpl::apply< \ ArrayType, \ typename Seq::value_type, boost::mpl::size<Seq> \ >::type value_type; \ \ static value_type const value; \ \ operator value_type const&() const{ \ return value; \ } \ }; \ \ template<typename Seq, typename ArrayType> \ typename c_array_impl<Seq, n, ArrayType>::value_type const \ c_array_impl<Seq, n, ArrayType>::value = PP_C_ARRYA_AC_C_INITIALIZER(n); BOOST_PP_REPEAT_FROM_TO(1, C_ARRAY_LIMIT_SIZE, PP_C_ARRAY, _) #undef PP_C_ARRAY #undef PP_C_ARRAY_AC_C #undef PP_C_ARRYA_AC_C_INITIALIZER } // namespace detail template< typename Seq, typename ArrayType = detail::array_type<boost::mpl::_1, boost::mpl::_2> > struct c_array : detail::c_array_impl<Seq, boost::mpl::size<Seq>::value, ArrayType>{}; #include <boost/mpl/vector.hpp> #include <boost/mpl/vector_c.hpp> #include <boost/mpl/range_c.hpp> #include <boost/range/algorithm/for_each.hpp> #include <boost/range/algorithm/equal.hpp> #include <boost/lambda/lambda.hpp> #include <boost/assert.hpp> #include <boost/range/irange.hpp> #include <vector> #include <iostream> namespace mpl = boost::mpl; int main(){ boost::array<int, 4> v = {10, 3, 5, 2}; BOOST_ASSERT(boost::equal( v, c_array<mpl::vector_c<int, 10, 3, 5, 2> >::value )); boost::for_each( c_array<mpl::range_c<int, 0, 5> >::value, std::cout << boost::lambda::_1 << "," ); std::cout << std::endl; std::vector<int> v2 = c_array<mpl::range_c<int, -5, 5>, std::vector<mpl::_1> >::value; boost::for_each( v2, std::cout << boost::lambda::_1 << "," ); return 0; }