/* * Copyright Andrey Semashev 2007 - 2015. * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) */ /*! * \file keyword.hpp * \author Andrey Semashev * \date 29.01.2012 * * The header contains attribute keyword declaration. */ #ifndef BOOST_LOG_EXPRESSIONS_KEYWORD_HPP_INCLUDED_ #define BOOST_LOG_EXPRESSIONS_KEYWORD_HPP_INCLUDED_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef BOOST_HAS_PRAGMA_ONCE #pragma once #endif namespace boost { BOOST_LOG_OPEN_NAMESPACE namespace expressions { /*! * This class implements an expression template keyword. It is used to start template expressions involving attribute values. */ template< typename DescriptorT, template< typename > class ActorT > struct attribute_keyword { //! Self type typedef attribute_keyword this_type; //! Attribute descriptor type typedef DescriptorT descriptor_type; BOOST_PROTO_BASIC_EXTENDS(typename proto::terminal< descriptor_type >::type, this_type, phoenix::phoenix_domain) //! Attribute value type typedef typename descriptor_type::value_type value_type; //! Returns attribute name static attribute_name get_name() { return descriptor_type::get_name(); } //! Expression with cached attribute name typedef attribute_actor< value_type, fallback_to_none, descriptor_type, ActorT > or_none_result_type; //! Generates an expression that extracts the attribute value or a default value static or_none_result_type or_none() { typedef typename or_none_result_type::terminal_type result_terminal; typename or_none_result_type::base_type act = {{ result_terminal(get_name()) }}; return or_none_result_type(act); } //! Expression with cached attribute name typedef attribute_actor< value_type, fallback_to_throw, descriptor_type, ActorT > or_throw_result_type; //! Generates an expression that extracts the attribute value or throws an exception static or_throw_result_type or_throw() { typedef typename or_throw_result_type::terminal_type result_terminal; typename or_throw_result_type::base_type act = {{ result_terminal(get_name()) }}; return or_throw_result_type(act); } //! Generates an expression that extracts the attribute value or a default value template< typename DefaultT > static attribute_actor< value_type, fallback_to_default< DefaultT >, descriptor_type, ActorT > or_default(DefaultT const& def_val) { typedef attribute_actor< value_type, fallback_to_default< DefaultT >, descriptor_type, ActorT > or_default_result_type; typedef typename or_default_result_type::terminal_type result_terminal; typename or_default_result_type::base_type act = {{ result_terminal(get_name(), def_val) }}; return or_default_result_type(act); } }; } // namespace expressions BOOST_LOG_CLOSE_NAMESPACE // namespace log #ifndef BOOST_LOG_DOXYGEN_PASS namespace proto { namespace detail { // This hack is needed in order to cache attribute name into the expression terminal when the template // expression is constructed. The standard way through a custom domain doesn't work because phoenix::actor // is bound to phoenix_domain. template< typename DescriptorT, template< typename > class ActorT, typename DomainT > struct protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT > { typedef boost::log::expressions::attribute_keyword< DescriptorT, ActorT > keyword_type; typedef typename keyword_type::or_none_result_type result_type; result_type operator() (keyword_type const& keyword) const { return keyword.or_none(); } }; template< typename DescriptorT, template< typename > class ActorT, typename DomainT > struct protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >&, DomainT > : public protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT > { }; template< typename DescriptorT, template< typename > class ActorT, typename DomainT > struct protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT > const&, DomainT > : public protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT > { }; template< typename DescriptorT, template< typename > class ActorT, typename DomainT > struct protoify< boost::reference_wrapper< boost::log::expressions::attribute_keyword< DescriptorT, ActorT > >, DomainT > : public protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT > { }; template< typename DescriptorT, template< typename > class ActorT, typename DomainT > struct protoify< boost::reference_wrapper< boost::log::expressions::attribute_keyword< DescriptorT, ActorT > > const, DomainT > : public protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT > { }; template< typename DescriptorT, template< typename > class ActorT, typename DomainT > struct protoify< boost::reference_wrapper< const boost::log::expressions::attribute_keyword< DescriptorT, ActorT > >, DomainT > : public protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT > { }; template< typename DescriptorT, template< typename > class ActorT, typename DomainT > struct protoify< boost::reference_wrapper< const boost::log::expressions::attribute_keyword< DescriptorT, ActorT > > const, DomainT > : public protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT > { }; } // namespace detail } // namespace proto #endif // !defined(BOOST_LOG_DOXYGEN_PASS) } // namespace boost #ifndef BOOST_LOG_DOXYGEN_PASS #define BOOST_LOG_ATTRIBUTE_KEYWORD_TYPE_IMPL(keyword_, name_, value_type_, tag_ns_)\ namespace tag_ns_\ {\ struct keyword_ :\ public ::boost::log::expressions::keyword_descriptor\ {\ typedef value_type_ value_type;\ static ::boost::log::attribute_name get_name() { return ::boost::log::attribute_name(name_); }\ };\ }\ typedef ::boost::log::expressions::attribute_keyword< tag_ns_::keyword_ > BOOST_PP_CAT(keyword_, _type); #define BOOST_LOG_ATTRIBUTE_KEYWORD_IMPL(keyword_, name_, value_type_, tag_ns_)\ BOOST_LOG_ATTRIBUTE_KEYWORD_TYPE_IMPL(keyword_, name_, value_type_, tag_ns_)\ const BOOST_PP_CAT(keyword_, _type) keyword_ = {}; #endif // BOOST_LOG_DOXYGEN_PASS /*! * \brief The macro declares an attribute keyword type * * The macro should be used at a namespace scope. It expands into an attribute keyword type definition, including the * \c tag namespace and the keyword tag type within which has the following layout: * * \code * namespace tag * { * struct keyword_ : * public boost::log::expressions::keyword_descriptor * { * typedef value_type_ value_type; * static boost::log::attribute_name get_name(); * }; * } * * typedef boost::log::expressions::attribute_keyword< tag::keyword_ > keyword_type; * \endcode * * The \c get_name method returns the attribute name. * * \note This macro only defines the type of the keyword. To also define the keyword object, use * the \c BOOST_LOG_ATTRIBUTE_KEYWORD macro instead. * * \param keyword_ Keyword name * \param name_ Attribute name string * \param value_type_ Attribute value type */ #define BOOST_LOG_ATTRIBUTE_KEYWORD_TYPE(keyword_, name_, value_type_)\ BOOST_LOG_ATTRIBUTE_KEYWORD_TYPE_IMPL(keyword_, name_, value_type_, tag) /*! * \brief The macro declares an attribute keyword * * The macro provides definitions similar to \c BOOST_LOG_ATTRIBUTE_KEYWORD_TYPE and additionally * defines the keyword object. * * \param keyword_ Keyword name * \param name_ Attribute name string * \param value_type_ Attribute value type */ #define BOOST_LOG_ATTRIBUTE_KEYWORD(keyword_, name_, value_type_)\ BOOST_LOG_ATTRIBUTE_KEYWORD_IMPL(keyword_, name_, value_type_, tag) #include #if defined(BOOST_LOG_TRIVIAL_HPP_INCLUDED_) #include #endif #endif // BOOST_LOG_EXPRESSIONS_KEYWORD_HPP_INCLUDED_