Imported Upstream version 1.57.0
[platform/upstream/boost.git] / boost / log / expressions / keyword.hpp
1 /*
2  *          Copyright Andrey Semashev 2007 - 2014.
3  * Distributed under the Boost Software License, Version 1.0.
4  *    (See accompanying file LICENSE_1_0.txt or copy at
5  *          http://www.boost.org/LICENSE_1_0.txt)
6  */
7 /*!
8  * \file   keyword.hpp
9  * \author Andrey Semashev
10  * \date   29.01.2012
11  *
12  * The header contains attribute keyword declaration.
13  */
14
15 #ifndef BOOST_LOG_EXPRESSIONS_KEYWORD_HPP_INCLUDED_
16 #define BOOST_LOG_EXPRESSIONS_KEYWORD_HPP_INCLUDED_
17
18 #include <boost/ref.hpp>
19 #include <boost/proto/extends.hpp>
20 #include <boost/proto/make_expr.hpp>
21 #include <boost/phoenix/core/actor.hpp>
22 #include <boost/phoenix/core/domain.hpp>
23 #include <boost/phoenix/core/environment.hpp>
24 #include <boost/fusion/sequence/intrinsic/at.hpp>
25 #include <boost/preprocessor/cat.hpp>
26 #include <boost/log/detail/config.hpp>
27 #include <boost/log/detail/custom_terminal_spec.hpp>
28 #include <boost/log/expressions/keyword_fwd.hpp>
29 #include <boost/log/expressions/is_keyword_descriptor.hpp>
30 #include <boost/log/expressions/attr.hpp>
31 #include <boost/log/attributes/attribute_name.hpp>
32 #include <boost/log/attributes/value_extraction.hpp>
33 #include <boost/log/attributes/fallback_policy.hpp>
34 #include <boost/log/detail/header.hpp>
35
36 #ifdef BOOST_HAS_PRAGMA_ONCE
37 #pragma once
38 #endif
39
40 namespace boost {
41
42 BOOST_LOG_OPEN_NAMESPACE
43
44 namespace expressions {
45
46 /*!
47  * This class implements an expression template keyword. It is used to start template expressions involving attribute values.
48  */
49 template< typename DescriptorT, template< typename > class ActorT >
50 struct attribute_keyword
51 {
52     //! Self type
53     typedef attribute_keyword this_type;
54     //! Attribute descriptor type
55     typedef DescriptorT descriptor_type;
56
57     BOOST_PROTO_BASIC_EXTENDS(typename proto::terminal< descriptor_type >::type, this_type, phoenix::phoenix_domain)
58
59     //! Attribute value type
60     typedef typename descriptor_type::value_type value_type;
61
62     //! Returns attribute name
63     static attribute_name get_name() { return descriptor_type::get_name(); }
64
65     //! Expression with cached attribute name
66     typedef attribute_actor<
67         value_type,
68         fallback_to_none,
69         descriptor_type,
70         ActorT
71     > or_none_result_type;
72
73     //! Generates an expression that extracts the attribute value or a default value
74     static or_none_result_type or_none()
75     {
76         typedef typename or_none_result_type::terminal_type result_terminal;
77         typename or_none_result_type::base_type act = {{ result_terminal(get_name()) }};
78         return or_none_result_type(act);
79     }
80
81     //! Expression with cached attribute name
82     typedef attribute_actor<
83         value_type,
84         fallback_to_throw,
85         descriptor_type,
86         ActorT
87     > or_throw_result_type;
88
89     //! Generates an expression that extracts the attribute value or throws an exception
90     static or_throw_result_type or_throw()
91     {
92         typedef typename or_throw_result_type::terminal_type result_terminal;
93         typename or_throw_result_type::base_type act = {{ result_terminal(get_name()) }};
94         return or_throw_result_type(act);
95     }
96
97     //! Generates an expression that extracts the attribute value or a default value
98     template< typename DefaultT >
99     static attribute_actor<
100         value_type,
101         fallback_to_default< DefaultT >,
102         descriptor_type,
103         ActorT
104     > or_default(DefaultT const& def_val)
105     {
106         typedef attribute_actor<
107             value_type,
108             fallback_to_default< DefaultT >,
109             descriptor_type,
110             ActorT
111         > or_default_result_type;
112         typedef typename or_default_result_type::terminal_type result_terminal;
113         typename or_default_result_type::base_type act = {{ result_terminal(get_name(), def_val) }};
114         return or_default_result_type(act);
115     }
116 };
117
118 } // namespace expressions
119
120 BOOST_LOG_CLOSE_NAMESPACE // namespace log
121
122 #ifndef BOOST_LOG_DOXYGEN_PASS
123
124 namespace proto {
125
126 namespace detail {
127
128 // This hack is needed in order to cache attribute name into the expression terminal when the template
129 // expression is constructed. The standard way through a custom domain doesn't work because phoenix::actor
130 // is bound to phoenix_domain.
131 template< typename DescriptorT, template< typename > class ActorT, typename DomainT >
132 struct protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT >
133 {
134     typedef boost::log::expressions::attribute_keyword< DescriptorT, ActorT > keyword_type;
135     typedef typename keyword_type::or_none_result_type result_type;
136
137     result_type operator() (keyword_type const& keyword) const
138     {
139         return keyword.or_none();
140     }
141 };
142
143 template< typename DescriptorT, template< typename > class ActorT, typename DomainT >
144 struct protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >&, DomainT > :
145     public protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT >
146 {
147 };
148
149 template< typename DescriptorT, template< typename > class ActorT, typename DomainT >
150 struct protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT > const&, DomainT > :
151     public protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT >
152 {
153 };
154
155 template< typename DescriptorT, template< typename > class ActorT, typename DomainT >
156 struct protoify< boost::reference_wrapper< boost::log::expressions::attribute_keyword< DescriptorT, ActorT > >, DomainT > :
157     public protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT >
158 {
159 };
160
161 template< typename DescriptorT, template< typename > class ActorT, typename DomainT >
162 struct protoify< boost::reference_wrapper< boost::log::expressions::attribute_keyword< DescriptorT, ActorT > > const, DomainT > :
163     public protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT >
164 {
165 };
166
167 template< typename DescriptorT, template< typename > class ActorT, typename DomainT >
168 struct protoify< boost::reference_wrapper< const boost::log::expressions::attribute_keyword< DescriptorT, ActorT > >, DomainT > :
169     public protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT >
170 {
171 };
172
173 template< typename DescriptorT, template< typename > class ActorT, typename DomainT >
174 struct protoify< boost::reference_wrapper< const boost::log::expressions::attribute_keyword< DescriptorT, ActorT > > const, DomainT > :
175     public protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT >
176 {
177 };
178
179 } // namespace detail
180
181 } // namespace proto
182
183 #endif // !defined(BOOST_LOG_DOXYGEN_PASS)
184
185 } // namespace boost
186
187 #ifndef BOOST_LOG_DOXYGEN_PASS
188
189 #define BOOST_LOG_ATTRIBUTE_KEYWORD_TYPE_IMPL(keyword_, name_, value_type_, tag_ns_)\
190     namespace tag_ns_\
191     {\
192         struct keyword_ :\
193             public ::boost::log::expressions::keyword_descriptor\
194         {\
195             typedef value_type_ value_type;\
196             static ::boost::log::attribute_name get_name() { return ::boost::log::attribute_name(name_); }\
197         };\
198     }\
199     typedef ::boost::log::expressions::attribute_keyword< tag_ns_::keyword_ > BOOST_PP_CAT(keyword_, _type);
200
201 #define BOOST_LOG_ATTRIBUTE_KEYWORD_IMPL(keyword_, name_, value_type_, tag_ns_)\
202     BOOST_LOG_ATTRIBUTE_KEYWORD_TYPE_IMPL(keyword_, name_, value_type_, tag_ns_)\
203     const BOOST_PP_CAT(keyword_, _type) keyword_ = {};
204
205 #endif // BOOST_LOG_DOXYGEN_PASS
206
207 /*!
208  * \brief The macro declares an attribute keyword type
209  *
210  * The macro should be used at a namespace scope. It expands into an attribute keyword type definition, including the
211  * \c tag namespace and the keyword tag type within which has the following layout:
212  *
213  * \code
214  * namespace tag
215  * {
216  *   struct keyword_ :
217  *     public boost::log::expressions::keyword_descriptor
218  *   {
219  *     typedef value_type_ value_type;
220  *     static boost::log::attribute_name get_name();
221  *   };
222  * }
223  *
224  * typedef boost::log::expressions::attribute_keyword< tag::keyword_ > keyword_type;
225  * \endcode
226  *
227  * The \c get_name method returns the attribute name.
228  *
229  * \note This macro only defines the type of the keyword. To also define the keyword object, use
230  *       the \c BOOST_LOG_ATTRIBUTE_KEYWORD macro instead.
231  *
232  * \param keyword_ Keyword name
233  * \param name_ Attribute name string
234  * \param value_type_ Attribute value type
235  */
236 #define BOOST_LOG_ATTRIBUTE_KEYWORD_TYPE(keyword_, name_, value_type_)\
237     BOOST_LOG_ATTRIBUTE_KEYWORD_TYPE_IMPL(keyword_, name_, value_type_, tag)
238
239 /*!
240  * \brief The macro declares an attribute keyword
241  *
242  * The macro provides definitions similar to \c BOOST_LOG_ATTRIBUTE_KEYWORD_TYPE and additionally
243  * defines the keyword object.
244  *
245  * \param keyword_ Keyword name
246  * \param name_ Attribute name string
247  * \param value_type_ Attribute value type
248  */
249 #define BOOST_LOG_ATTRIBUTE_KEYWORD(keyword_, name_, value_type_)\
250     BOOST_LOG_ATTRIBUTE_KEYWORD_IMPL(keyword_, name_, value_type_, tag)
251
252 #include <boost/log/detail/footer.hpp>
253
254 #if defined(BOOST_LOG_TRIVIAL_HPP_INCLUDED_)
255 #include <boost/log/detail/trivial_keyword.hpp>
256 #endif
257
258 #endif // BOOST_LOG_EXPRESSIONS_KEYWORD_HPP_INCLUDED_