// Compile with: g++ -std=gnu++0x -I. -o terminal_test ./terminal_test.cpp #include #include #include #include #include #include #include #include using namespace boost; namespace boost { namespace phoenix { namespace result_of { template< typename T > struct is_nullary< T, typename T::_is_my_terminal > : public mpl::false_ { }; } // namespace result_of template< typename T > struct is_custom_terminal< T, typename T::_is_my_terminal > : public mpl::true_ { }; template< typename T > struct custom_terminal< T, typename T::_is_my_terminal > { typedef custom_terminal< T, typename T::_is_my_terminal > this_type; template< typename > struct result; template< typename ThisT, typename TermT, typename ContextT > struct result< ThisT(TermT, ContextT) > { typedef typename remove_cv< typename remove_reference< TermT >::type >::type term; typedef typename boost::result_of< const term(ContextT) >::type type; }; template< typename ContextT > typename result< const this_type(T, ContextT) >::type operator() (T const& term, ContextT& ctx) const { return term(ctx); } }; } // namespace phoenix } // namespace boost namespace my { struct argument { std::string m_value; explicit argument(std::string const& value) : m_value(value) { } }; template< typename LeftT > class output_terminal { public: typedef void _is_my_terminal; //! Self type typedef output_terminal this_type; //! Result type definition template< typename > struct result; template< typename ContextT > struct result< this_type(ContextT) > { typedef typename remove_cv< typename remove_reference< ContextT >::type >::type context_type; typedef typename phoenix::evaluator::impl< typename LeftT::proto_base_expr&, context_type, phoenix::unused >::result_type type; }; template< typename ContextT > struct result< const this_type(ContextT) > { typedef typename remove_cv< typename remove_reference< ContextT >::type >::type context_type; typedef typename phoenix::evaluator::impl< typename LeftT::proto_base_expr const&, context_type, phoenix::unused >::result_type type; }; private: //! Left argument actor LeftT m_left; //! Right argument std::string m_right; public: //! Initializing constructor output_terminal(LeftT const& left, std::string const& right) : m_left(left), m_right(right) { } //! Invokation operator template< typename ContextT > typename result< this_type(ContextT) >::type operator() (ContextT const& ctx) { typedef typename result< this_type(ContextT) >::type result_type; result_type strm = phoenix::eval(m_left, ctx); strm << m_right; return strm; } //! Invokation operator template< typename ContextT > typename result< const this_type(ContextT) >::type operator() (ContextT const& ctx) const { typedef typename result< const this_type(ContextT) >::type result_type; result_type strm = phoenix::eval(m_left, ctx); strm << m_right; return strm; } }; template< typename LeftExprT > inline phoenix::actor< output_terminal< phoenix::actor< LeftExprT > > > operator<< (phoenix::actor< LeftExprT > const& left, argument const& right) { phoenix::actor< output_terminal< phoenix::actor< LeftExprT > > > res = { output_terminal< phoenix::actor< LeftExprT > >(left, right.m_value) }; return res; } typedef phoenix::expression::argument< 1 >::type stream_type; const stream_type stream = {}; } // namespace my int main(int, char*[]) { function< void (std::ostream&) > func; func = my::operator<< (my::stream, my::argument("Hello, world!")); func(std::cout); return 0; }