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)
9 * \author Andrey Semashev
12 * The header contains attribute keyword declaration.
15 #ifndef BOOST_LOG_EXPRESSIONS_KEYWORD_HPP_INCLUDED_
16 #define BOOST_LOG_EXPRESSIONS_KEYWORD_HPP_INCLUDED_
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>
36 #ifdef BOOST_HAS_PRAGMA_ONCE
42 BOOST_LOG_OPEN_NAMESPACE
44 namespace expressions {
47 * This class implements an expression template keyword. It is used to start template expressions involving attribute values.
49 template< typename DescriptorT, template< typename > class ActorT >
50 struct attribute_keyword
53 typedef attribute_keyword this_type;
54 //! Attribute descriptor type
55 typedef DescriptorT descriptor_type;
57 BOOST_PROTO_BASIC_EXTENDS(typename proto::terminal< descriptor_type >::type, this_type, phoenix::phoenix_domain)
59 //! Attribute value type
60 typedef typename descriptor_type::value_type value_type;
62 //! Returns attribute name
63 static attribute_name get_name() { return descriptor_type::get_name(); }
65 //! Expression with cached attribute name
66 typedef attribute_actor<
71 > or_none_result_type;
73 //! Generates an expression that extracts the attribute value or a default value
74 static or_none_result_type or_none()
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);
81 //! Expression with cached attribute name
82 typedef attribute_actor<
87 > or_throw_result_type;
89 //! Generates an expression that extracts the attribute value or throws an exception
90 static or_throw_result_type or_throw()
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);
97 //! Generates an expression that extracts the attribute value or a default value
98 template< typename DefaultT >
99 static attribute_actor<
101 fallback_to_default< DefaultT >,
104 > or_default(DefaultT const& def_val)
106 typedef attribute_actor<
108 fallback_to_default< DefaultT >,
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);
118 } // namespace expressions
120 BOOST_LOG_CLOSE_NAMESPACE // namespace log
122 #ifndef BOOST_LOG_DOXYGEN_PASS
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 >
134 typedef boost::log::expressions::attribute_keyword< DescriptorT, ActorT > keyword_type;
135 typedef typename keyword_type::or_none_result_type result_type;
137 result_type operator() (keyword_type const& keyword) const
139 return keyword.or_none();
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 >
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 >
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 >
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 >
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 >
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 >
179 } // namespace detail
183 #endif // !defined(BOOST_LOG_DOXYGEN_PASS)
187 #ifndef BOOST_LOG_DOXYGEN_PASS
189 #define BOOST_LOG_ATTRIBUTE_KEYWORD_TYPE_IMPL(keyword_, name_, value_type_, tag_ns_)\
193 public ::boost::log::expressions::keyword_descriptor\
195 typedef value_type_ value_type;\
196 static ::boost::log::attribute_name get_name() { return ::boost::log::attribute_name(name_); }\
199 typedef ::boost::log::expressions::attribute_keyword< tag_ns_::keyword_ > BOOST_PP_CAT(keyword_, _type);
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_ = {};
205 #endif // BOOST_LOG_DOXYGEN_PASS
208 * \brief The macro declares an attribute keyword type
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:
217 * public boost::log::expressions::keyword_descriptor
219 * typedef value_type_ value_type;
220 * static boost::log::attribute_name get_name();
224 * typedef boost::log::expressions::attribute_keyword< tag::keyword_ > keyword_type;
227 * The \c get_name method returns the attribute name.
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.
232 * \param keyword_ Keyword name
233 * \param name_ Attribute name string
234 * \param value_type_ Attribute value type
236 #define BOOST_LOG_ATTRIBUTE_KEYWORD_TYPE(keyword_, name_, value_type_)\
237 BOOST_LOG_ATTRIBUTE_KEYWORD_TYPE_IMPL(keyword_, name_, value_type_, tag)
240 * \brief The macro declares an attribute keyword
242 * The macro provides definitions similar to \c BOOST_LOG_ATTRIBUTE_KEYWORD_TYPE and additionally
243 * defines the keyword object.
245 * \param keyword_ Keyword name
246 * \param name_ Attribute name string
247 * \param value_type_ Attribute value type
249 #define BOOST_LOG_ATTRIBUTE_KEYWORD(keyword_, name_, value_type_)\
250 BOOST_LOG_ATTRIBUTE_KEYWORD_IMPL(keyword_, name_, value_type_, tag)
252 #include <boost/log/detail/footer.hpp>
254 #if defined(BOOST_LOG_TRIVIAL_HPP_INCLUDED_)
255 #include <boost/log/detail/trivial_keyword.hpp>
258 #endif // BOOST_LOG_EXPRESSIONS_KEYWORD_HPP_INCLUDED_