phoenix使い始め。(lazy_make_shared)

phoenixが強力らしいので使ってみることにした。


main.cpp

#include <iostream>
#include <vector>

#include <boost/spirit/home/phoenix.hpp>

#include <pstade/oven/algorithm.hpp>
#include <pstade/oven/initial_values.hpp>

#include "./lazy_make_shared.hpp"

class A
{
public:
    A(int n)
        :   n_(n)
    {
        std::cout << "created(" << n << ")" << std::endl;
    }

    friend
        std::ostream & operator<< (std::ostream &os, A const &a)
    {
        return os << "A(" << a.n_ << ")";
    }

private:
    int n_;
};

int main()
{
    namespace oven = pstade::oven;
    namespace phx = boost::phoenix;

    std::vector<int> const vs = oven::initial_values(1, 3, 5, 7);

    std::vector< boost::shared_ptr<A> > as;
    
    std::cout << "create A" << std::endl;

    oven::for_each(
        vs,
        phx::push_back(
            phx::ref(as),
            hwm::lazy_make_shared<A>::get()(phx::arg_names::arg1)
        )
    );

    std::cout << "display A" << std::endl;
    
    oven::for_each(as, std::cout << *phx::arg_names::arg1 << std::endl);
}
create A
created(1)
created(3)
created(5)
created(7)
display A
A(1)
A(3)
A(5)
A(7)


lazy_make_shared.hpp

#ifndef HWM_LAZY_MAKE_SHARED_HPP
#define HWM_LAZY_MAKE_SHARED_HPP

#define HWM_LAZY_MAKE_SHARED_ARG_LIMIT 10

#include <boost/spirit/home/phoenix/function/function.hpp>
#include "./lazy_make_shared_impl.hpp"

namespace hwm {

template<typename T>
struct lazy_make_shared
{
    typedef
        boost::phoenix::function< lazy_make_shared_impl<T> >
    value_type;

    static
    value_type const get() { return lazy_make_shared_impl<T>(); }
};

}   //namespace hwm
#endif  //HWM_LAZY_MAKE_SHARED_HPP


lazy_make_shared_impl.hpp

#if !BOOST_PP_IS_ITERATING

    #ifndef HWM_LAZY_MAKE_SHARED_IMPL_HPP
    #define HWM_LAZY_MAKE_SHARED_IMPL_HPP

    #include <boost/make_shared.hpp>
    #include <boost/preprocessor/cat.hpp>
    #include <boost/preprocessor/repetition/enum.hpp>
    #include <boost/preprocessor/iteration/iterate.hpp>

    namespace hwm {

    template<typename T>
    struct lazy_make_shared_impl
    {
        struct unused_type {};

        #define HWM_LOCAL_DEF_UNUSED(_, N, data) \
            typename BOOST_PP_CAT(unused, N) = unused_type

        template<
            BOOST_PP_ENUM(HWM_LAZY_MAKE_SHARED_ARG_LIMIT, HWM_LOCAL_DEF_UNUSED, _)
        >
        struct result
        {
            typedef boost::shared_ptr<T> type;
        };

        typedef typename result<>::type result_type;

    #undef HWM_LOCAL_DEF_UNUSED

    #define BOOST_PP_ITERATION_PARAMS_1 (3, (0, HWM_LAZY_MAKE_SHARED_ARG_LIMIT, "lazy_make_shared_impl.hpp"))
    #include BOOST_PP_ITERATE()

    };

    }   //namespace hwm

    #endif  //HWM_LAZY_MAKE_SHARED_IMPL_HPP

#else   //iterating

#define N BOOST_PP_ITERATION()

#if N == 0
        typename result<>::type
            operator()() const {
            return
                boost::make_shared<T>();
        }

#else
        template<
            BOOST_PP_ENUM_PARAMS(N, typename Arg)
        >
        typename result<BOOST_PP_ENUM_PARAMS(N, Arg)>::type
            operator() (BOOST_PP_ENUM_BINARY_PARAMS(N, Arg, const &arg)) const {
            return
                boost::make_shared<T>(
                    BOOST_PP_ENUM_PARAMS(N, arg) );
        }
#endif

#endif   //N == 0

#endif   //iterating

・・・と、ここまで書いてから、

    oven::for_each(
        vs,
        phx::push_back(
            phx::ref(as),
            //hwm::lazy_make_shared<A>::get()(phx::arg_names::arg1)
            phx::construct< boost::shared_ptr<A> >(
                phx::new_<A>(phx::arg_names::arg1)
            )
        )
    );

これで良いじゃんということに気づいて(´・ω・`)