Ticket #7300: terminal_test.cpp

File terminal_test.cpp, 4.0 KB (added by Andrey Semashev, 10 years ago)

Code sample that illustrates the problem

Line 
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
12using namespace boost;
13
14namespace boost {
15
16namespace phoenix {
17
18namespace result_of {
19
20template< typename T >
21struct is_nullary< T, typename T::_is_my_terminal > :
22 public mpl::false_
23{
24};
25
26} // namespace result_of
27
28template< typename T >
29struct is_custom_terminal< T, typename T::_is_my_terminal > :
30 public mpl::true_
31{
32};
33
34template< typename T >
35struct 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
60namespace my {
61
62struct argument
63{
64 std::string m_value;
65
66 explicit argument(std::string const& value) : m_value(value)
67 {
68 }
69};
70
71template< typename LeftT >
72class output_terminal
73{
74public:
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
106private:
107 //! Left argument actor
108 LeftT m_left;
109 //! Right argument
110 std::string m_right;
111
112public:
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
139template< typename LeftExprT >
140inline phoenix::actor< output_terminal< phoenix::actor< LeftExprT > > >
141operator<< (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
147typedef phoenix::expression::argument< 1 >::type stream_type;
148const stream_type stream = {};
149
150} // namespace my
151
152int 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}