1 /* 2 * Copyright Andrey Semashev 2007 - 2015. 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 get_nameboost::expressions::attribute_keyword63 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 or_noneboost::expressions::attribute_keyword74 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 or_throwboost::expressions::attribute_keyword90 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 or_defaultboost::expressions::attribute_keyword104 > 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 operator ()boost::proto::detail::protoify137 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 BOOST_INLINE_VARIABLE 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_ 259