boost::array 型のメンバ変数を初期化子リストで初期化する
追記: 名前を変更 (elements → braced2).boost::array に限らず { { args... } } で初期化できるものなら大体使えます.また少し変更すれば { args... } などで初期化することもできます.
C++03 では,配列型のメンバ変数を初期化子リストで初期化することはできません (参照).しかし,boost::array であれば,変換関数を使って初期化子リストでの初期化を実現することができます.
例
#include <string> #include <iostream> #include <boost/array.hpp> #include <boost/range/iterator_range.hpp> #include "braced2.hpp" struct T_hello { boost::array<std::string, 5> m_words; T_hello() : m_words(braced2("Hello", ", ", "world", "!")) // the 5th element is value-initialized {} void operator()() const { std::cout << boost::make_iterator_range(m_words) << "\n"; } }; T_hello const hello; int main() { hello(); }
ヘッダ
#ifndef BRACED2_HPP #define BRACED2_HPP #include <boost/functional/forward_adapter.hpp> #include <boost/preprocessor/cat.hpp> #include <boost/preprocessor/iteration/local.hpp> #include <boost/preprocessor/repetition/enum_params.hpp> #include <boost/preprocessor/repetition/repeat.hpp> #include <boost/preprocessor/repetition/enum_binary_params.hpp> #include <boost/preprocessor/repetition/enum.hpp> #include <boost/preprocessor/facilities/intercept.hpp> #if !defined(BRACED2_MAX_ARITY) #define BRACED2_MAX_ARITY BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY #endif namespace braced2_detail { #define BRACED2_member_decl(z, i, unused) BOOST_PP_CAT(A, i) BOOST_PP_CAT(m_a, i); #define BRACED2_member_init(z, i, unused) BOOST_PP_CAT(m_a, i)(BOOST_PP_CAT(a, i)) #define BOOST_PP_LOCAL_MACRO(n) \ template <BOOST_PP_ENUM_PARAMS(n, class A)> \ struct BOOST_PP_CAT(result, n) \ { \ BOOST_PP_REPEAT(n, BRACED2_member_decl, ~) \ BOOST_PP_CAT(result, n)(BOOST_PP_ENUM_BINARY_PARAMS(n, A, a)) \ : BOOST_PP_ENUM(n, BRACED2_member_init, ~) \ {}; \ template <class T> \ operator T() const \ { \ T t = { { BOOST_PP_ENUM_PARAMS(n, m_a) } }; \ return t; \ } \ }; \ /**/ #define BOOST_PP_LOCAL_LIMITS (1, BRACED2_MAX_ARITY) #include BOOST_PP_LOCAL_ITERATE() #undef BRACED2_member_init #undef BRACED2_member_decl struct aux_ { template <class> struct result; #define BOOST_PP_LOCAL_MACRO(n) \ template <class Me, BOOST_PP_ENUM_PARAMS(n, class A)> \ struct result<Me(BOOST_PP_ENUM_PARAMS(n, A))> \ { \ typedef BOOST_PP_CAT(result, n)<BOOST_PP_ENUM_PARAMS(n, A)> type; \ }; \ template <BOOST_PP_ENUM_PARAMS(n, class A)> \ typename result<aux_ const(BOOST_PP_ENUM_BINARY_PARAMS(n, A, &BOOST_PP_INTERCEPT))>::type \ operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, A, &a)) const \ { \ return BOOST_PP_CAT(result, n)<BOOST_PP_ENUM_BINARY_PARAMS(n, A, &BOOST_PP_INTERCEPT)>(BOOST_PP_ENUM_PARAMS(n, a)); \ } \ /**/ #define BOOST_PP_LOCAL_LIMITS (1, BRACED2_MAX_ARITY) #include BOOST_PP_LOCAL_ITERATE() }; } // namespace braced2_detail typedef boost::forward_adapter<braced2_detail::aux_> T_braced2; T_braced2 const braced2; #endif
Sandbox の assign_v2 にも似たようなものがありますが,C++03 用の実装は残念な感じでした.
おまけ
それ Boost.Egg でできるよ!
#include <boost/egg/implicit.hpp> #include <boost/egg/generator.hpp> #include <boost/egg/construct_braced2.hpp> #include <boost/mpl/always.hpp> #include <boost/mpl/placeholders.hpp> #include <boost/mpl/protect.hpp> typedef boost::egg::implicit< boost::egg::generator< boost::mpl::always<boost::mpl::_1>, boost::use_default, boost::mpl::protect<boost::egg::X_construct_braced2<> > > >::type T_braced2; T_braced2 const braced2 = BOOST_EGG_IMPLICIT();