Guest User

Problem with Boost.Phoenix custom terminal

a guest
Aug 25th, 2012
59
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // Compile with: g++ -std=gnu++0x -I. -o terminal_test ./terminal_test.cpp
  2.  
  3. #include <string>
  4. #include <iostream>
  5. #include <boost/phoenix.hpp>
  6. #include <boost/function.hpp>
  7. #include <boost/mpl/bool.hpp>
  8. #include <boost/utility/result_of.hpp>
  9. #include <boost/type_traits/remove_cv.hpp>
  10. #include <boost/type_traits/remove_reference.hpp>
  11.  
  12. using namespace boost;
  13.  
  14. namespace boost {
  15.  
  16. namespace phoenix {
  17.  
  18. namespace result_of {
  19.  
  20. template< typename T >
  21. struct is_nullary< T, typename T::_is_my_terminal > :
  22.     public mpl::false_
  23. {
  24. };
  25.  
  26. } // namespace result_of
  27.  
  28. template< typename T >
  29. struct is_custom_terminal< T, typename T::_is_my_terminal > :
  30.     public mpl::true_
  31. {
  32. };
  33.  
  34. template< typename T >
  35. struct custom_terminal< T, typename T::_is_my_terminal >
  36. {
  37.     typedef custom_terminal< T, typename T::_is_my_terminal > this_type;
  38.  
  39.     template< typename >
  40.     struct result;
  41.  
  42.     template< typename ThisT, typename TermT, typename ContextT >
  43.     struct result< ThisT(TermT, ContextT) >
  44.     {
  45.         typedef typename remove_cv< typename remove_reference< TermT >::type >::type term;
  46.         typedef typename boost::result_of< const term(ContextT) >::type type;
  47.     };
  48.  
  49.     template< typename ContextT >
  50.     typename result< const this_type(T, ContextT) >::type operator() (T const& term, ContextT& ctx) const
  51.     {
  52.         return term(ctx);
  53.     }
  54. };
  55.  
  56. } // namespace phoenix
  57.  
  58. } // namespace boost
  59.  
  60. namespace my {
  61.  
  62. struct argument
  63. {
  64.     std::string m_value;
  65.  
  66.     explicit argument(std::string const& value) : m_value(value)
  67.     {
  68.     }
  69. };
  70.  
  71. template< typename LeftT >
  72. class output_terminal
  73. {
  74. public:
  75.     typedef void _is_my_terminal;
  76.  
  77.     //! Self type
  78.     typedef output_terminal this_type;
  79.  
  80.     //! Result type definition
  81.     template< typename >
  82.     struct result;
  83.  
  84.     template< typename ContextT >
  85.     struct result< this_type(ContextT) >
  86.     {
  87.         typedef typename remove_cv< typename remove_reference< ContextT >::type >::type context_type;
  88.         typedef typename phoenix::evaluator::impl<
  89.             typename LeftT::proto_base_expr&,
  90.             context_type,
  91.             phoenix::unused
  92.         >::result_type type;
  93.     };
  94.  
  95.     template< typename ContextT >
  96.     struct result< const this_type(ContextT) >
  97.     {
  98.         typedef typename remove_cv< typename remove_reference< ContextT >::type >::type context_type;
  99.         typedef typename phoenix::evaluator::impl<
  100.             typename LeftT::proto_base_expr const&,
  101.             context_type,
  102.             phoenix::unused
  103.         >::result_type type;
  104.     };
  105.  
  106. private:
  107.     //! Left argument actor
  108.     LeftT m_left;
  109.     //! Right argument
  110.     std::string m_right;
  111.  
  112. public:
  113.     //! Initializing constructor
  114.     output_terminal(LeftT const& left, std::string const& right) : m_left(left), m_right(right)
  115.     {
  116.     }
  117.  
  118.     //! Invokation operator
  119.     template< typename ContextT >
  120.     typename result< this_type(ContextT) >::type operator() (ContextT const& ctx)
  121.     {
  122.         typedef typename result< this_type(ContextT) >::type result_type;
  123.         result_type strm = phoenix::eval(m_left, ctx);
  124.         strm << m_right;
  125.         return strm;
  126.     }
  127.  
  128.     //! Invokation operator
  129.     template< typename ContextT >
  130.     typename result< const this_type(ContextT) >::type operator() (ContextT const& ctx) const
  131.     {
  132.         typedef typename result< const this_type(ContextT) >::type result_type;
  133.         result_type strm = phoenix::eval(m_left, ctx);
  134.         strm << m_right;
  135.         return strm;
  136.     }
  137. };
  138.  
  139. template< typename LeftExprT >
  140. inline phoenix::actor< output_terminal< phoenix::actor< LeftExprT > > >
  141. operator<< (phoenix::actor< LeftExprT > const& left, argument const& right)
  142. {
  143.     phoenix::actor< output_terminal< phoenix::actor< LeftExprT > > > res = { output_terminal< phoenix::actor< LeftExprT > >(left, right.m_value) };
  144.     return res;
  145. }
  146.  
  147. typedef phoenix::expression::argument< 1 >::type stream_type;
  148. const stream_type stream = {};
  149.  
  150. } // namespace my
  151.  
  152. int main(int, char*[])
  153. {
  154.     function< void (std::ostream&) > func;
  155.  
  156.     func = my::operator<< (my::stream, my::argument("Hello, world!"));
  157.  
  158.     func(std::cout);
  159.  
  160.     return 0;
  161. }
RAW Paste Data