Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:39:22

0001 /*
0002  *          Copyright Andrey Semashev 2007 - 2015.
0003  * Distributed under the Boost Software License, Version 1.0.
0004  *    (See accompanying file LICENSE_1_0.txt or copy at
0005  *          http://www.boost.org/LICENSE_1_0.txt)
0006  */
0007 /*!
0008  * \file   formatters/char_decorator.hpp
0009  * \author Andrey Semashev
0010  * \date   17.11.2012
0011  *
0012  * The header contains implementation of a character decorator.
0013  */
0014 
0015 #ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_CHAR_DECORATOR_HPP_INCLUDED_
0016 #define BOOST_LOG_EXPRESSIONS_FORMATTERS_CHAR_DECORATOR_HPP_INCLUDED_
0017 
0018 #include <vector>
0019 #include <string>
0020 #include <iterator>
0021 #include <boost/assert.hpp>
0022 #include <boost/mpl/bool.hpp>
0023 #include <boost/range/begin.hpp>
0024 #include <boost/range/end.hpp>
0025 #include <boost/range/size.hpp>
0026 #include <boost/range/const_iterator.hpp>
0027 #include <boost/range/value_type.hpp>
0028 #include <boost/move/core.hpp>
0029 #include <boost/move/utility_core.hpp>
0030 #include <boost/core/addressof.hpp>
0031 #include <boost/phoenix/core/actor.hpp>
0032 #include <boost/phoenix/core/meta_grammar.hpp>
0033 #include <boost/phoenix/core/terminal_fwd.hpp>
0034 #include <boost/phoenix/core/is_nullary.hpp>
0035 #include <boost/phoenix/core/environment.hpp>
0036 #include <boost/phoenix/support/vector.hpp>
0037 #include <boost/fusion/sequence/intrinsic/at_c.hpp>
0038 #include <boost/type_traits/is_same.hpp>
0039 #include <boost/type_traits/remove_cv.hpp>
0040 #include <boost/type_traits/remove_reference.hpp>
0041 #include <boost/log/detail/config.hpp>
0042 #include <boost/log/detail/custom_terminal_spec.hpp>
0043 #include <boost/log/detail/deduce_char_type.hpp>
0044 #include <boost/log/detail/sfinae_tools.hpp>
0045 #include <boost/log/utility/formatting_ostream.hpp>
0046 #include <boost/log/detail/header.hpp>
0047 
0048 #ifdef BOOST_HAS_PRAGMA_ONCE
0049 #pragma once
0050 #endif
0051 
0052 namespace boost {
0053 
0054 BOOST_LOG_OPEN_NAMESPACE
0055 
0056 namespace expressions {
0057 
0058 namespace aux {
0059 
0060 template< typename RangeT >
0061 struct string_const_iterator : range_const_iterator< RangeT > {};
0062 template< >
0063 struct string_const_iterator< char* > { typedef char* type; };
0064 template< >
0065 struct string_const_iterator< const char* > { typedef const char* type; };
0066 template< >
0067 struct string_const_iterator< wchar_t* > { typedef wchar_t* type; };
0068 template< >
0069 struct string_const_iterator< const wchar_t* > { typedef const wchar_t* type; };
0070 
0071 } // namespace aux
0072 
0073 /*!
0074  * A simple character decorator implementation. This implementation replaces string patterns in the source string with
0075  * the fixed replacements. Source patterns and replacements can be specified at the object construction.
0076  */
0077 template< typename CharT >
0078 class pattern_replacer
0079 {
0080 public:
0081     //! Result type
0082     typedef void result_type;
0083 
0084     //! Character type
0085     typedef CharT char_type;
0086     //! String type
0087     typedef std::basic_string< char_type > string_type;
0088 
0089 private:
0090     //! Lengths of source pattern and replacement
0091     struct string_lengths
0092     {
0093         unsigned int from_len, to_len;
0094     };
0095 
0096     //! List of the decorations to apply
0097     typedef std::vector< string_lengths > string_lengths_list;
0098 
0099 private:
0100     //! Characters of the interleaved source patterns and replacements
0101     string_type m_decoration_chars;
0102     //! List of the decorations to apply
0103     string_lengths_list m_string_lengths;
0104 
0105 public:
0106     /*!
0107      * Initializing constructor. Creates a pattern replacer with the specified \a decorations.
0108      * The provided decorations must be a sequence of \c std::pair of strings. The first element
0109      * of each pair is the source pattern, and the second one is the corresponding replacement.
0110      */
0111     template< typename RangeT >
0112     explicit pattern_replacer(RangeT const& decorations
0113 #ifndef BOOST_LOG_DOXYGEN_PASS
0114         // This is needed for a workaround against an MSVC-10 and older bug in constructor overload resolution
0115         , typename boost::enable_if_has_type< typename range_const_iterator< RangeT >::type, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()
0116 #endif
0117     )
0118     {
0119         typedef typename range_const_iterator< RangeT >::type iterator;
0120         for (iterator it = boost::begin(decorations), end_ = boost::end(decorations); it != end_; ++it)
0121         {
0122             string_lengths lens;
0123             {
0124                 typedef typename aux::string_const_iterator< typename range_value< RangeT >::type::first_type >::type first_iterator;
0125                 first_iterator b = string_begin(it->first), e = string_end(it->first);
0126                 lens.from_len = static_cast< unsigned int >(std::distance(b, e));
0127                 m_decoration_chars.append(b, e);
0128             }
0129             {
0130                 typedef typename aux::string_const_iterator< typename range_value< RangeT >::type::second_type >::type second_iterator;
0131                 second_iterator b = string_begin(it->second), e = string_end(it->second);
0132                 lens.to_len = static_cast< unsigned int >(std::distance(b, e));
0133                 m_decoration_chars.append(b, e);
0134             }
0135             m_string_lengths.push_back(lens);
0136         }
0137     }
0138     /*!
0139      * Initializing constructor. Creates a pattern replacer with decorations specified
0140      * in form of two same-sized string sequences. Each <tt>i</tt>'th decoration will be
0141      * <tt>from[i]</tt> -> <tt>to[i]</tt>.
0142      */
0143     template< typename FromRangeT, typename ToRangeT >
0144     pattern_replacer(FromRangeT const& from, ToRangeT const& to)
0145     {
0146         typedef typename range_const_iterator< FromRangeT >::type iterator1;
0147         typedef typename range_const_iterator< ToRangeT >::type iterator2;
0148         iterator1 it1 = boost::begin(from), end1 = boost::end(from);
0149         iterator2 it2 = boost::begin(to), end2 = boost::end(to);
0150         for (; it1 != end1 && it2 != end2; ++it1, ++it2)
0151         {
0152             string_lengths lens;
0153             {
0154                 typedef typename aux::string_const_iterator< typename range_value< FromRangeT >::type >::type from_iterator;
0155                 from_iterator b = string_begin(*it1), e = string_end(*it1);
0156                 lens.from_len = static_cast< unsigned int >(std::distance(b, e));
0157                 m_decoration_chars.append(b, e);
0158             }
0159             {
0160                 typedef typename aux::string_const_iterator< typename range_value< ToRangeT >::type >::type to_iterator;
0161                 to_iterator b = string_begin(*it2), e = string_end(*it2);
0162                 lens.to_len = static_cast< unsigned int >(std::distance(b, e));
0163                 m_decoration_chars.append(b, e);
0164             }
0165             m_string_lengths.push_back(lens);
0166         }
0167 
0168         // Both sequences should be of the same size
0169         BOOST_ASSERT(it1 == end1);
0170         BOOST_ASSERT(it2 == end2);
0171     }
0172     //! Copy constructor
0173     pattern_replacer(pattern_replacer const& that) : m_decoration_chars(that.m_decoration_chars), m_string_lengths(that.m_string_lengths)
0174     {
0175     }
0176 
0177     //! Applies string replacements starting from the specified position
0178     result_type operator() (string_type& str, typename string_type::size_type start_pos = 0) const
0179     {
0180         typedef typename string_type::size_type size_type;
0181 
0182         const char_type* from_chars = m_decoration_chars.c_str();
0183         for (typename string_lengths_list::const_iterator it = m_string_lengths.begin(), end = m_string_lengths.end(); it != end; ++it)
0184         {
0185             const unsigned int from_len = it->from_len, to_len = it->to_len;
0186             const char_type* const to_chars = from_chars + from_len;
0187             for (size_type pos = str.find(from_chars, start_pos, from_len); pos != string_type::npos; pos = str.find(from_chars, pos, from_len))
0188             {
0189                 str.replace(pos, from_len, to_chars, to_len);
0190                 pos += to_len;
0191             }
0192             from_chars = to_chars + to_len;
0193         }
0194     }
0195 
0196 private:
0197     static char_type* string_begin(char_type* p)
0198     {
0199         return p;
0200     }
0201     static const char_type* string_begin(const char_type* p)
0202     {
0203         return p;
0204     }
0205     template< typename RangeT >
0206     static typename range_const_iterator< RangeT >::type string_begin(RangeT const& r)
0207     {
0208         return boost::begin(r);
0209     }
0210 
0211     static char_type* string_end(char_type* p)
0212     {
0213         return p + std::char_traits< char_type >::length(p);
0214     }
0215     static const char_type* string_end(const char_type* p)
0216     {
0217         return p + std::char_traits< char_type >::length(p);
0218     }
0219     template< typename RangeT >
0220     static typename range_const_iterator< RangeT >::type string_end(RangeT const& r)
0221     {
0222         return boost::end(r);
0223     }
0224 };
0225 
0226 namespace aux {
0227 
0228 //! Character decorator stream output terminal
0229 template< typename LeftT, typename SubactorT, typename ImplT >
0230 class char_decorator_output_terminal
0231 {
0232 private:
0233     //! Self type
0234     typedef char_decorator_output_terminal< LeftT, SubactorT, ImplT > this_type;
0235 
0236 public:
0237 #ifndef BOOST_LOG_DOXYGEN_PASS
0238     //! Internal typedef for type categorization
0239     typedef void _is_boost_log_terminal;
0240 #endif
0241 
0242     //! Implementation type
0243     typedef ImplT impl_type;
0244 
0245     //! Character type
0246     typedef typename impl_type::char_type char_type;
0247     //! String type
0248     typedef typename impl_type::string_type string_type;
0249     //! Adopted actor type
0250     typedef SubactorT subactor_type;
0251 
0252     //! Result type definition
0253     template< typename >
0254     struct result;
0255 
0256     template< typename ThisT, typename ContextT >
0257     struct result< ThisT(ContextT) >
0258     {
0259         typedef typename remove_cv< typename remove_reference< ContextT >::type >::type context_type;
0260         typedef typename phoenix::evaluator::impl<
0261             typename LeftT::proto_base_expr&,
0262             context_type,
0263             phoenix::unused
0264         >::result_type type;
0265     };
0266 
0267 private:
0268     //! Left argument actor
0269     LeftT m_left;
0270     //! Adopted formatter actor
0271     subactor_type m_subactor;
0272     //! Implementation type
0273     impl_type m_impl;
0274 
0275 public:
0276     /*!
0277      * Initializing constructor. Creates decorator of the \a fmt formatter with the specified \a decorations.
0278      */
0279     char_decorator_output_terminal(LeftT const& left, subactor_type const& sub, impl_type const& impl) :
0280         m_left(left), m_subactor(sub), m_impl(impl)
0281     {
0282     }
0283     /*!
0284      * Copy constructor
0285      */
0286     char_decorator_output_terminal(char_decorator_output_terminal const& that) :
0287         m_left(that.m_left), m_subactor(that.m_subactor), m_impl(that.m_impl)
0288     {
0289     }
0290 
0291     /*!
0292      * Invokation operator
0293      */
0294     template< typename ContextT >
0295     typename result< this_type(ContextT const&) >::type operator() (ContextT const& ctx)
0296     {
0297         // Flush the stream and keep the current write position in the target string
0298         typedef typename result< this_type(ContextT const&) >::type result_type;
0299         result_type strm = phoenix::eval(m_left, ctx);
0300         strm.flush();
0301         typename string_type::size_type const start_pos = strm.rdbuf()->storage()->size();
0302 
0303         // Invoke the adopted formatter
0304         phoenix::eval(m_subactor, ctx);
0305 
0306         // Flush the buffered characters and apply decorations
0307         strm.flush();
0308         m_impl(*strm.rdbuf()->storage(), start_pos);
0309         strm.rdbuf()->ensure_max_size();
0310 
0311         return strm;
0312     }
0313 
0314     /*!
0315      * Invokation operator
0316      */
0317     template< typename ContextT >
0318     typename result< const this_type(ContextT const&) >::type operator() (ContextT const& ctx) const
0319     {
0320         // Flush the stream and keep the current write position in the target string
0321         typedef typename result< const this_type(ContextT const&) >::type result_type;
0322         result_type strm = phoenix::eval(m_left, ctx);
0323         strm.flush();
0324         typename string_type::size_type const start_pos = strm.rdbuf()->storage()->size();
0325 
0326         // Invoke the adopted formatter
0327         phoenix::eval(m_subactor, ctx);
0328 
0329         // Flush the buffered characters and apply decorations
0330         strm.flush();
0331         m_impl(*strm.rdbuf()->storage(), start_pos);
0332         strm.rdbuf()->ensure_max_size();
0333 
0334         return strm;
0335     }
0336 
0337     BOOST_DELETED_FUNCTION(char_decorator_output_terminal())
0338 };
0339 
0340 } // namespace aux
0341 
0342 /*!
0343  * Character decorator terminal class. This formatter allows to modify strings generated by other
0344  * formatters on character level. The most obvious application of decorators is replacing
0345  * a certain set of characters with decorated equivalents to satisfy requirements of
0346  * text-based sinks.
0347  *
0348  * The \c char_decorator_terminal class aggregates the formatter being decorated, and a set
0349  * of string pairs that are used as decorations. All decorations are applied sequentially.
0350  * The \c char_decorator_terminal class is a formatter itself, so it can be used to construct
0351  * more complex formatters, including nesting decorators.
0352  */
0353 template< typename SubactorT, typename ImplT >
0354 class char_decorator_terminal
0355 {
0356 private:
0357     //! Self type
0358     typedef char_decorator_terminal< SubactorT, ImplT > this_type;
0359 
0360 public:
0361 #ifndef BOOST_LOG_DOXYGEN_PASS
0362     //! Internal typedef for type categorization
0363     typedef void _is_boost_log_terminal;
0364 #endif
0365 
0366     //! Implementation type
0367     typedef ImplT impl_type;
0368     //! Character type
0369     typedef typename impl_type::char_type char_type;
0370     //! String type
0371     typedef typename impl_type::string_type string_type;
0372     //! Stream type
0373     typedef basic_formatting_ostream< char_type > stream_type;
0374     //! Adopted actor type
0375     typedef SubactorT subactor_type;
0376 
0377     //! Result type definition
0378     typedef string_type result_type;
0379 
0380 private:
0381     //! Adopted formatter actor
0382     subactor_type m_subactor;
0383     //! Implementation
0384     impl_type m_impl;
0385 
0386 public:
0387     /*!
0388      * Initializing constructor.
0389      */
0390     char_decorator_terminal(subactor_type const& sub, impl_type const& impl) : m_subactor(sub), m_impl(impl)
0391     {
0392     }
0393     /*!
0394      * Copy constructor
0395      */
0396     char_decorator_terminal(char_decorator_terminal const& that) : m_subactor(that.m_subactor), m_impl(that.m_impl)
0397     {
0398     }
0399 
0400     /*!
0401      * \returns Adopted subactor
0402      */
0403     subactor_type const& get_subactor() const
0404     {
0405         return m_subactor;
0406     }
0407 
0408     /*!
0409      * \returns Implementation
0410      */
0411     impl_type const& get_impl() const
0412     {
0413         return m_impl;
0414     }
0415 
0416     /*!
0417      * Invokation operator
0418      */
0419     template< typename ContextT >
0420     result_type operator() (ContextT const& ctx)
0421     {
0422         string_type str;
0423         stream_type strm(str);
0424 
0425         // Invoke the adopted formatter
0426         typedef phoenix::vector3<
0427             subactor_type*,
0428             typename fusion::result_of::at_c<
0429                 typename remove_cv<
0430                     typename remove_reference<
0431                         typename phoenix::result_of::env< ContextT const& >::type
0432                     >::type
0433                 >::type::args_type,
0434                 0
0435             >::type,
0436             stream_type&
0437         > env_type;
0438         env_type env = { boost::addressof(m_subactor), fusion::at_c< 0 >(phoenix::env(ctx).args()), strm };
0439         phoenix::eval(m_subactor, phoenix::make_context(env, phoenix::actions(ctx)));
0440 
0441         // Flush the buffered characters and apply decorations
0442         strm.flush();
0443         m_impl(*strm.rdbuf()->storage());
0444 
0445         return BOOST_LOG_NRVO_RESULT(str);
0446     }
0447 
0448     /*!
0449      * Invokation operator
0450      */
0451     template< typename ContextT >
0452     result_type operator() (ContextT const& ctx) const
0453     {
0454         string_type str;
0455         stream_type strm(str);
0456 
0457         // Invoke the adopted formatter
0458         typedef phoenix::vector3<
0459             const subactor_type*,
0460             typename fusion::result_of::at_c<
0461                 typename remove_cv<
0462                     typename remove_reference<
0463                         typename phoenix::result_of::env< ContextT const& >::type
0464                     >::type
0465                 >::type::args_type,
0466                 0
0467             >::type,
0468             stream_type&
0469         > env_type;
0470         env_type env = { boost::addressof(m_subactor), fusion::at_c< 0 >(phoenix::env(ctx).args()), strm };
0471         phoenix::eval(m_subactor, phoenix::make_context(env, phoenix::actions(ctx)));
0472 
0473         // Flush the buffered characters and apply decorations
0474         strm.flush();
0475         m_impl(*strm.rdbuf()->storage());
0476 
0477         return BOOST_LOG_NRVO_RESULT(str);
0478     }
0479 
0480     BOOST_DELETED_FUNCTION(char_decorator_terminal())
0481 };
0482 
0483 /*!
0484  * Character decorator actor
0485  */
0486 template< typename SubactorT, typename ImplT, template< typename > class ActorT = phoenix::actor >
0487 class char_decorator_actor :
0488     public ActorT< char_decorator_terminal< SubactorT, ImplT > >
0489 {
0490 public:
0491     //! Base terminal type
0492     typedef char_decorator_terminal< SubactorT, ImplT > terminal_type;
0493     //! Character type
0494     typedef typename terminal_type::char_type char_type;
0495 
0496     //! Base actor type
0497     typedef ActorT< terminal_type > base_type;
0498 
0499 public:
0500     //! Initializing constructor
0501     explicit char_decorator_actor(base_type const& act) : base_type(act)
0502     {
0503     }
0504 
0505     //! Returns reference to the terminal
0506     terminal_type const& get_terminal() const
0507     {
0508         return this->proto_expr_.child0;
0509     }
0510 };
0511 
0512 #ifndef BOOST_LOG_DOXYGEN_PASS
0513 
0514 #define BOOST_LOG_AUX_OVERLOAD(left_ref, right_ref)\
0515     template< typename LeftExprT, typename SubactorT, typename ImplT, template< typename > class ActorT >\
0516     BOOST_FORCEINLINE phoenix::actor< aux::char_decorator_output_terminal< phoenix::actor< LeftExprT >, SubactorT, ImplT > >\
0517     operator<< (phoenix::actor< LeftExprT > left_ref left, char_decorator_actor< SubactorT, ImplT, ActorT > right_ref right)\
0518     {\
0519         typedef aux::char_decorator_output_terminal< phoenix::actor< LeftExprT >, SubactorT, ImplT > terminal_type;\
0520         phoenix::actor< terminal_type > actor = {{ terminal_type(left, right.get_terminal().get_subactor(), right.get_terminal().get_impl()) }};\
0521         return actor;\
0522     }
0523 
0524 #include <boost/log/detail/generate_overloads.hpp>
0525 
0526 #undef BOOST_LOG_AUX_OVERLOAD
0527 
0528 #endif // BOOST_LOG_DOXYGEN_PASS
0529 
0530 namespace aux {
0531 
0532 template< typename RangeT >
0533 class char_decorator_gen1
0534 {
0535     RangeT const& m_decorations;
0536 
0537     typedef typename boost::log::aux::deduce_char_type< typename range_value< RangeT >::type::first_type >::type char_type;
0538 
0539 public:
0540     explicit char_decorator_gen1(RangeT const& decorations) : m_decorations(decorations)
0541     {
0542     }
0543 
0544     template< typename SubactorT >
0545     BOOST_FORCEINLINE char_decorator_actor< SubactorT, pattern_replacer< char_type > > operator[] (SubactorT const& subactor) const
0546     {
0547         typedef pattern_replacer< char_type > replacer_type;
0548         typedef char_decorator_actor< SubactorT, replacer_type > result_type;
0549         typedef typename result_type::terminal_type terminal_type;
0550         typename result_type::base_type act = {{ terminal_type(subactor, replacer_type(m_decorations)) }};
0551         return result_type(act);
0552     }
0553 };
0554 
0555 template< typename FromRangeT, typename ToRangeT >
0556 class char_decorator_gen2
0557 {
0558     FromRangeT const& m_from;
0559     ToRangeT const& m_to;
0560 
0561     typedef typename boost::log::aux::deduce_char_type< typename range_value< FromRangeT >::type >::type from_char_type;
0562     typedef typename boost::log::aux::deduce_char_type< typename range_value< ToRangeT >::type >::type to_char_type;
0563     static_assert(is_same< from_char_type, to_char_type >::value, "Boost.Log: character decorator cannot be instantiated with different character types for source and replacement strings");
0564 
0565 public:
0566     char_decorator_gen2(FromRangeT const& from, ToRangeT const& to) : m_from(from), m_to(to)
0567     {
0568     }
0569 
0570     template< typename SubactorT >
0571     BOOST_FORCEINLINE char_decorator_actor< SubactorT, pattern_replacer< from_char_type > > operator[] (SubactorT const& subactor) const
0572     {
0573         typedef pattern_replacer< from_char_type > replacer_type;
0574         typedef char_decorator_actor< SubactorT, replacer_type > result_type;
0575         typedef typename result_type::terminal_type terminal_type;
0576         typename result_type::base_type act = {{ terminal_type(subactor, replacer_type(m_from, m_to)) }};
0577         return result_type(act);
0578     }
0579 };
0580 
0581 } // namespace aux
0582 
0583 /*!
0584  * The function returns a decorator generator object. The generator provides <tt>operator[]</tt> that can be used
0585  * to construct the actual decorator.
0586  *
0587  * \param decorations A sequence of string pairs that will be used as decorations. Every <tt>decorations[i].first</tt>
0588  *                    substring occurrence in the output will be replaced with <tt>decorations[i].second</tt>.
0589  */
0590 template< typename RangeT >
0591 BOOST_FORCEINLINE aux::char_decorator_gen1< RangeT > char_decor(RangeT const& decorations)
0592 {
0593     return aux::char_decorator_gen1< RangeT >(decorations);
0594 }
0595 
0596 /*!
0597  * The function returns a decorator generator object. The generator provides <tt>operator[]</tt> that can be used
0598  * to construct the actual decorator.
0599  *
0600  * \param from A sequence of strings that will be sought in the output.
0601  * \param to A sequence of strings that will be used as replacements.
0602  *
0603  * \note The \a from and \a to sequences mush be of the same size. Every <tt>from[i]</tt>
0604  *       substring occurrence in the output will be replaced with <tt>to[i]</tt>.
0605  */
0606 template< typename FromRangeT, typename ToRangeT >
0607 BOOST_FORCEINLINE aux::char_decorator_gen2< FromRangeT, ToRangeT > char_decor(FromRangeT const& from, ToRangeT const& to)
0608 {
0609     return aux::char_decorator_gen2< FromRangeT, ToRangeT >(from, to);
0610 }
0611 
0612 } // namespace expressions
0613 
0614 BOOST_LOG_CLOSE_NAMESPACE // namespace log
0615 
0616 #ifndef BOOST_LOG_DOXYGEN_PASS
0617 
0618 namespace phoenix {
0619 
0620 namespace result_of {
0621 
0622 template< typename SubactorT, typename ImplT >
0623 struct is_nullary< custom_terminal< boost::log::expressions::char_decorator_terminal< SubactorT, ImplT > > > :
0624     public mpl::false_
0625 {
0626 };
0627 
0628 template< typename LeftT, typename SubactorT, typename ImplT >
0629 struct is_nullary< custom_terminal< boost::log::expressions::aux::char_decorator_output_terminal< LeftT, SubactorT, ImplT > > > :
0630     public mpl::false_
0631 {
0632 };
0633 
0634 } // namespace result_of
0635 
0636 } // namespace phoenix
0637 
0638 #endif
0639 
0640 } // namespace boost
0641 
0642 #include <boost/log/detail/footer.hpp>
0643 
0644 #endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_CHAR_DECORATOR_HPP_INCLUDED_