1 ///////////////////////////////////////////////////////////////////////////////
2 /// \file as_expr.hpp
3 /// Contains definition of the as_expr\<\> and as_child\<\> helper class
4 /// templates used to implement proto::domain's as_expr\<\> and as_child\<\>
5 /// member templates.
6 //
7 //  Copyright 2010 Eric Niebler. Distributed under the Boost
8 //  Software License, Version 1.0. (See accompanying file
9 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10 
11 #ifndef BOOST_PROTO_DETAIL_AS_EXPR_HPP_EAN_06_09_2010
12 #define BOOST_PROTO_DETAIL_AS_EXPR_HPP_EAN_06_09_2010
13 
14 #include <boost/config.hpp>
15 #include <boost/detail/workaround.hpp>
16 #include <boost/type_traits/remove_const.hpp>
17 #include <boost/proto/proto_fwd.hpp>
18 #include <boost/proto/args.hpp>
19 
20 #if defined(_MSC_VER)
21 # pragma warning(push)
22 # pragma warning(disable : 4714) // function 'xxx' marked as __forceinline not inlined
23 #endif
24 
25 namespace boost { namespace proto { namespace detail
26 {
27 
28     ////////////////////////////////////////////////////////////////////////////////////////////////
29     template<typename Generator>
30     struct base_generator
31     {
32         typedef Generator type;
33     };
34 
35     template<typename Generator>
36     struct base_generator<use_basic_expr<Generator> >
37     {
38         typedef Generator type;
39     };
40 
41     ////////////////////////////////////////////////////////////////////////////////////////////////
42     template<typename T, typename Generator, bool WantsBasicExpr>
43     struct as_expr;
44 
45     ////////////////////////////////////////////////////////////////////////////////////////////////
46     template<typename T, typename Generator>
47     struct as_expr<T, Generator, false>
48     {
49         typedef typename term_traits<T &>::value_type value_type;
50         typedef proto::expr<proto::tag::terminal, term<value_type>, 0> expr_type;
51         typedef typename Generator::template result<Generator(expr_type)>::type result_type;
52 
53         BOOST_FORCEINLINE
operator ()boost::proto::detail::as_expr54         result_type operator()(T &t) const
55         {
56             return Generator()(expr_type::make(t));
57         }
58     };
59 
60     ////////////////////////////////////////////////////////////////////////////////////////////////
61     template<typename T, typename Generator>
62     struct as_expr<T, Generator, true>
63     {
64         typedef typename term_traits<T &>::value_type value_type;
65         typedef proto::basic_expr<proto::tag::terminal, term<value_type>, 0> expr_type;
66         typedef typename Generator::template result<Generator(expr_type)>::type result_type;
67 
68         BOOST_FORCEINLINE
operator ()boost::proto::detail::as_expr69         result_type operator()(T &t) const
70         {
71             return Generator()(expr_type::make(t));
72         }
73     };
74 
75     ////////////////////////////////////////////////////////////////////////////////////////////////
76     template<typename T>
77     struct as_expr<T, proto::default_generator, false>
78     {
79         typedef typename term_traits<T &>::value_type value_type;
80         typedef proto::expr<proto::tag::terminal, term<value_type>, 0> result_type;
81 
82         BOOST_FORCEINLINE
operator ()boost::proto::detail::as_expr83         result_type operator()(T &t) const
84         {
85             return result_type::make(t);
86         }
87     };
88 
89     ////////////////////////////////////////////////////////////////////////////////////////////////
90     template<typename T>
91     struct as_expr<T, proto::default_generator, true>
92     {
93         typedef typename term_traits<T &>::value_type value_type;
94         typedef proto::basic_expr<proto::tag::terminal, term<value_type>, 0> result_type;
95 
96         BOOST_FORCEINLINE
operator ()boost::proto::detail::as_expr97         result_type operator()(T &t) const
98         {
99             return result_type::make(t);
100         }
101     };
102 
103     ////////////////////////////////////////////////////////////////////////////////////////////////
104     template<typename T, typename Generator, bool WantsBasicExpr>
105     struct as_child;
106 
107     ////////////////////////////////////////////////////////////////////////////////////////////////
108     template<typename T, typename Generator>
109     struct as_child<T, Generator, false>
110     {
111     #if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
112         typedef typename term_traits<T &>::reference reference;
113     #else
114         typedef T &reference;
115     #endif
116         typedef proto::expr<proto::tag::terminal, term<reference>, 0> expr_type;
117         typedef typename Generator::template result<Generator(expr_type)>::type result_type;
118 
119         BOOST_FORCEINLINE
operator ()boost::proto::detail::as_child120         result_type operator()(T &t) const
121         {
122             return Generator()(expr_type::make(t));
123         }
124     };
125 
126     ////////////////////////////////////////////////////////////////////////////////////////////////
127     template<typename T, typename Generator>
128     struct as_child<T, Generator, true>
129     {
130     #if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
131         typedef typename term_traits<T &>::reference reference;
132     #else
133         typedef T &reference;
134     #endif
135         typedef proto::basic_expr<proto::tag::terminal, term<reference>, 0> expr_type;
136         typedef typename Generator::template result<Generator(expr_type)>::type result_type;
137 
138         BOOST_FORCEINLINE
operator ()boost::proto::detail::as_child139         result_type operator()(T &t) const
140         {
141             return Generator()(expr_type::make(t));
142         }
143     };
144 
145     ////////////////////////////////////////////////////////////////////////////////////////////////
146     template<typename T>
147     struct as_child<T, proto::default_generator, false>
148     {
149     #if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
150         typedef typename term_traits<T &>::reference reference;
151     #else
152         typedef T &reference;
153     #endif
154         typedef proto::expr<proto::tag::terminal, term<reference>, 0> result_type;
155 
156         BOOST_FORCEINLINE
operator ()boost::proto::detail::as_child157         result_type operator()(T &t) const
158         {
159             return result_type::make(t);
160         }
161     };
162 
163     ////////////////////////////////////////////////////////////////////////////////////////////////
164     template<typename T>
165     struct as_child<T, proto::default_generator, true>
166     {
167     #if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
168         typedef typename term_traits<T &>::reference reference;
169     #else
170         typedef T &reference;
171     #endif
172         typedef proto::basic_expr<proto::tag::terminal, term<reference>, 0> result_type;
173 
174         BOOST_FORCEINLINE
operator ()boost::proto::detail::as_child175         result_type operator()(T &t) const
176         {
177             return result_type::make(t);
178         }
179     };
180 
181 }}}
182 
183 #if defined(_MSC_VER)
184 # pragma warning(pop)
185 #endif
186 
187 #endif
188