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   formatter.hpp
9  * \author Andrey Semashev
10  * \date   13.07.2012
11  *
12  * The header contains a formatter function object definition.
13  */
14 
15 #ifndef BOOST_LOG_EXPRESSIONS_FORMATTER_HPP_INCLUDED_
16 #define BOOST_LOG_EXPRESSIONS_FORMATTER_HPP_INCLUDED_
17 
18 #include <locale>
19 #include <ostream>
20 #include <boost/ref.hpp>
21 #include <boost/move/core.hpp>
22 #include <boost/move/utility_core.hpp>
23 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
24 #include <boost/type_traits/is_same.hpp>
25 #include <boost/type_traits/remove_cv.hpp>
26 #include <boost/log/detail/sfinae_tools.hpp>
27 #endif
28 #include <boost/log/detail/config.hpp>
29 #include <boost/log/detail/light_function.hpp>
30 #include <boost/log/attributes/attribute_value_set.hpp>
31 #include <boost/log/attributes/value_visitation.hpp>
32 #include <boost/log/core/record_view.hpp>
33 #include <boost/log/utility/formatting_ostream.hpp>
34 #include <boost/log/utility/functional/bind_output.hpp>
35 #include <boost/log/expressions/message.hpp>
36 #include <boost/log/detail/header.hpp>
37 
38 #ifdef BOOST_HAS_PRAGMA_ONCE
39 #pragma once
40 #endif
41 
42 namespace boost {
43 
44 BOOST_LOG_OPEN_NAMESPACE
45 
46 namespace expressions {
47 
48 namespace aux {
49 
50 // This reference class is a workaround for a Boost.Phoenix bug: https://svn.boost.org/trac/boost/ticket/9363
51 // It is needed to pass output streams by non-const reference to function objects wrapped in phoenix::bind and phoenix::function.
52 // It's an implementation detail and will be removed when Boost.Phoenix is fixed.
53 template< typename StreamT >
54 class stream_ref :
55     public reference_wrapper< StreamT >
56 {
57 public:
58     typedef typename StreamT::char_type char_type;
59     typedef typename StreamT::traits_type traits_type;
60     typedef typename StreamT::allocator_type allocator_type;
61     typedef typename StreamT::streambuf_type streambuf_type;
62     typedef typename StreamT::string_type string_type;
63     typedef typename StreamT::ostream_type ostream_type;
64     typedef typename StreamT::pos_type pos_type;
65     typedef typename StreamT::off_type off_type;
66     typedef typename StreamT::int_type int_type;
67 
68     typedef typename StreamT::failure failure;
69     typedef typename StreamT::fmtflags fmtflags;
70     typedef typename StreamT::iostate iostate;
71     typedef typename StreamT::openmode openmode;
72     typedef typename StreamT::seekdir seekdir;
73     typedef typename StreamT::Init Init;
74 
75     typedef typename StreamT::event event;
76     typedef typename StreamT::event_callback event_callback;
77 
78     typedef typename StreamT::sentry sentry;
79 
80     static BOOST_CONSTEXPR_OR_CONST fmtflags boolalpha = StreamT::boolalpha;
81     static BOOST_CONSTEXPR_OR_CONST fmtflags dec = StreamT::dec;
82     static BOOST_CONSTEXPR_OR_CONST fmtflags fixed = StreamT::fixed;
83     static BOOST_CONSTEXPR_OR_CONST fmtflags hex = StreamT::hex;
84     static BOOST_CONSTEXPR_OR_CONST fmtflags internal = StreamT::internal;
85     static BOOST_CONSTEXPR_OR_CONST fmtflags left = StreamT::left;
86     static BOOST_CONSTEXPR_OR_CONST fmtflags oct = StreamT::oct;
87     static BOOST_CONSTEXPR_OR_CONST fmtflags right = StreamT::right;
88     static BOOST_CONSTEXPR_OR_CONST fmtflags scientific = StreamT::scientific;
89     static BOOST_CONSTEXPR_OR_CONST fmtflags showbase = StreamT::showbase;
90     static BOOST_CONSTEXPR_OR_CONST fmtflags showpoint = StreamT::showpoint;
91     static BOOST_CONSTEXPR_OR_CONST fmtflags skipws = StreamT::skipws;
92     static BOOST_CONSTEXPR_OR_CONST fmtflags unitbuf = StreamT::unitbuf;
93     static BOOST_CONSTEXPR_OR_CONST fmtflags uppercase = StreamT::uppercase;
94     static BOOST_CONSTEXPR_OR_CONST fmtflags adjustfield = StreamT::adjustfield;
95     static BOOST_CONSTEXPR_OR_CONST fmtflags basefield = StreamT::basefield;
96     static BOOST_CONSTEXPR_OR_CONST fmtflags floatfield = StreamT::floatfield;
97 
98     static BOOST_CONSTEXPR_OR_CONST iostate badbit = StreamT::badbit;
99     static BOOST_CONSTEXPR_OR_CONST iostate eofbit = StreamT::eofbit;
100     static BOOST_CONSTEXPR_OR_CONST iostate failbit = StreamT::failbit;
101     static BOOST_CONSTEXPR_OR_CONST iostate goodbit = StreamT::goodbit;
102 
103     static BOOST_CONSTEXPR_OR_CONST openmode app = StreamT::app;
104     static BOOST_CONSTEXPR_OR_CONST openmode ate = StreamT::ate;
105     static BOOST_CONSTEXPR_OR_CONST openmode binary = StreamT::binary;
106     static BOOST_CONSTEXPR_OR_CONST openmode in = StreamT::in;
107     static BOOST_CONSTEXPR_OR_CONST openmode out = StreamT::out;
108     static BOOST_CONSTEXPR_OR_CONST openmode trunc = StreamT::trunc;
109 
110     static BOOST_CONSTEXPR_OR_CONST seekdir beg = StreamT::beg;
111     static BOOST_CONSTEXPR_OR_CONST seekdir cur = StreamT::cur;
112     static BOOST_CONSTEXPR_OR_CONST seekdir end = StreamT::end;
113 
114     static BOOST_CONSTEXPR_OR_CONST event erase_event = StreamT::erase_event;
115     static BOOST_CONSTEXPR_OR_CONST event imbue_event = StreamT::imbue_event;
116     static BOOST_CONSTEXPR_OR_CONST event copyfmt_event = StreamT::copyfmt_event;
117 
118 
stream_ref(StreamT & strm)119     BOOST_FORCEINLINE explicit stream_ref(StreamT& strm) : reference_wrapper< StreamT >(strm)
120     {
121     }
122 
123 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
124     template< typename T >
operator <<(T && val) const125     BOOST_FORCEINLINE StreamT& operator<< (T&& val) const
126     {
127         StreamT& strm = this->get();
128         strm << static_cast< T&& >(val);
129         return strm;
130     }
131 #if defined(BOOST_MSVC) && BOOST_MSVC < 1800
132     // MSVC 10 and 11 generate broken code for the perfect forwarding version above if T is an array type (e.g. a string literal)
133     template< typename T, unsigned int N >
operator <<(T (& val)[N]) const134     BOOST_FORCEINLINE StreamT& operator<< (T (&val)[N]) const
135     {
136         StreamT& strm = this->get();
137         strm << val;
138         return strm;
139     }
140 #endif
141 #else
142     template< typename T >
operator <<(T & val) const143     BOOST_FORCEINLINE StreamT& operator<< (T& val) const
144     {
145         StreamT& strm = this->get();
146         strm << val;
147         return strm;
148     }
149 
150     template< typename T >
operator <<(T const & val) const151     BOOST_FORCEINLINE StreamT& operator<< (T const& val) const
152     {
153         StreamT& strm = this->get();
154         strm << val;
155         return strm;
156     }
157 #endif
158 
attach(string_type & str) const159     BOOST_FORCEINLINE void attach(string_type& str) const { this->get().attach(str); }
detach() const160     BOOST_FORCEINLINE void detach() const { this->get().detach(); }
str() const161     BOOST_FORCEINLINE string_type const& str() const { return this->get().str(); }
stream() const162     BOOST_FORCEINLINE ostream_type& stream() const { return this->get().stream(); }
flags() const163     BOOST_FORCEINLINE fmtflags flags() const { return this->get().flags(); }
flags(fmtflags f) const164     BOOST_FORCEINLINE fmtflags flags(fmtflags f) const { return this->get().flags(f); }
setf(fmtflags f) const165     BOOST_FORCEINLINE fmtflags setf(fmtflags f) const { return this->get().setf(f); }
setf(fmtflags f,fmtflags mask) const166     BOOST_FORCEINLINE fmtflags setf(fmtflags f, fmtflags mask) const { return this->get().setf(f, mask); }
unsetf(fmtflags f) const167     BOOST_FORCEINLINE void unsetf(fmtflags f) const { this->get().unsetf(f); }
168 
precision() const169     BOOST_FORCEINLINE std::streamsize precision() const { return this->get().precision(); }
precision(std::streamsize p) const170     BOOST_FORCEINLINE std::streamsize precision(std::streamsize p) const { return this->get().precision(p); }
171 
width() const172     BOOST_FORCEINLINE std::streamsize width() const { return this->get().width(); }
width(std::streamsize w) const173     BOOST_FORCEINLINE std::streamsize width(std::streamsize w) const { return this->get().width(w); }
174 
getloc() const175     BOOST_FORCEINLINE std::locale getloc() const { return this->get().getloc(); }
imbue(std::locale const & loc) const176     BOOST_FORCEINLINE std::locale imbue(std::locale const& loc) const { return this->get().imbue(loc); }
177 
xalloc()178     static BOOST_FORCEINLINE int xalloc() { return StreamT::xalloc(); }
iword(int index) const179     BOOST_FORCEINLINE long& iword(int index) const { return this->get().iword(index); }
pword(int index) const180     BOOST_FORCEINLINE void*& pword(int index) const { return this->get().pword(index); }
181 
register_callback(event_callback fn,int index) const182     BOOST_FORCEINLINE void register_callback(event_callback fn, int index) const { this->get().register_callback(fn, index); }
183 
sync_with_stdio(bool sync=true)184     static BOOST_FORCEINLINE bool sync_with_stdio(bool sync = true) { return StreamT::sync_with_stdio(sync); }
185 
186     BOOST_EXPLICIT_OPERATOR_BOOL()
187     BOOST_FORCEINLINE bool operator! () const { return !this->get(); }
188 
rdstate() const189     BOOST_FORCEINLINE iostate rdstate() const { return this->get().rdstate(); }
clear(iostate state=goodbit) const190     BOOST_FORCEINLINE void clear(iostate state = goodbit) const { this->get().clear(state); }
setstate(iostate state) const191     BOOST_FORCEINLINE void setstate(iostate state) const { this->get().setstate(state); }
good() const192     BOOST_FORCEINLINE bool good() const { return this->get().good(); }
eof() const193     BOOST_FORCEINLINE bool eof() const { return this->get().eof(); }
fail() const194     BOOST_FORCEINLINE bool fail() const { return this->get().fail(); }
bad() const195     BOOST_FORCEINLINE bool bad() const { return this->get().bad(); }
196 
exceptions() const197     BOOST_FORCEINLINE iostate exceptions() const { return this->get().exceptions(); }
exceptions(iostate s) const198     BOOST_FORCEINLINE void exceptions(iostate s) const { this->get().exceptions(s); }
199 
tie() const200     BOOST_FORCEINLINE ostream_type* tie() const { return this->get().tie(); }
tie(ostream_type * strm) const201     BOOST_FORCEINLINE ostream_type* tie(ostream_type* strm) const { return this->get().tie(strm); }
202 
rdbuf() const203     BOOST_FORCEINLINE streambuf_type* rdbuf() const { return this->get().rdbuf(); }
204 
copyfmt(std::basic_ios<char_type,traits_type> & rhs) const205     BOOST_FORCEINLINE StreamT& copyfmt(std::basic_ios< char_type, traits_type >& rhs) const { return this->get().copyfmt(rhs); }
copyfmt(StreamT & rhs) const206     BOOST_FORCEINLINE StreamT& copyfmt(StreamT& rhs) const { return this->get().copyfmt(rhs); }
207 
fill() const208     BOOST_FORCEINLINE char_type fill() const { return this->get().fill(); }
fill(char_type ch) const209     BOOST_FORCEINLINE char_type fill(char_type ch) const { return this->get().fill(ch); }
210 
narrow(char_type ch,char def) const211     BOOST_FORCEINLINE char narrow(char_type ch, char def) const { return this->get().narrow(ch, def); }
widen(char ch) const212     BOOST_FORCEINLINE char_type widen(char ch) const { return this->get().widen(ch); }
213 
flush() const214     BOOST_FORCEINLINE StreamT& flush() const { return this->get().flush(); }
215 
tellp() const216     BOOST_FORCEINLINE pos_type tellp() const { return this->get().tellp(); }
seekp(pos_type pos) const217     BOOST_FORCEINLINE StreamT& seekp(pos_type pos) const { return this->get().seekp(pos); }
seekp(off_type off,std::ios_base::seekdir dir) const218     BOOST_FORCEINLINE StreamT& seekp(off_type off, std::ios_base::seekdir dir) const { return this->get().seekp(off, dir); }
219 
220     template< typename CharT >
221     BOOST_FORCEINLINE typename boost::log::aux::enable_if_streamable_char_type< CharT, StreamT& >::type
put(CharT c) const222     put(CharT c) const { return this->get().put(c); }
223 
224     template< typename CharT >
225     BOOST_FORCEINLINE typename boost::log::aux::enable_if_streamable_char_type< CharT, StreamT& >::type
write(const CharT * p,std::streamsize size) const226     write(const CharT* p, std::streamsize size) const { return this->get().write(p, size); }
227 };
228 
229 template< typename StreamT >
230 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::boolalpha;
231 template< typename StreamT >
232 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::dec;
233 template< typename StreamT >
234 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::fixed;
235 template< typename StreamT >
236 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::hex;
237 template< typename StreamT >
238 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::internal;
239 template< typename StreamT >
240 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::left;
241 template< typename StreamT >
242 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::oct;
243 template< typename StreamT >
244 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::right;
245 template< typename StreamT >
246 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::scientific;
247 template< typename StreamT >
248 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::showbase;
249 template< typename StreamT >
250 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::showpoint;
251 template< typename StreamT >
252 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::skipws;
253 template< typename StreamT >
254 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::unitbuf;
255 template< typename StreamT >
256 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::uppercase;
257 template< typename StreamT >
258 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::adjustfield;
259 template< typename StreamT >
260 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::basefield;
261 template< typename StreamT >
262 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::floatfield;
263 
264 template< typename StreamT >
265 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::iostate stream_ref< StreamT >::badbit;
266 template< typename StreamT >
267 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::iostate stream_ref< StreamT >::eofbit;
268 template< typename StreamT >
269 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::iostate stream_ref< StreamT >::failbit;
270 template< typename StreamT >
271 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::iostate stream_ref< StreamT >::goodbit;
272 
273 template< typename StreamT >
274 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::openmode stream_ref< StreamT >::app;
275 template< typename StreamT >
276 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::openmode stream_ref< StreamT >::ate;
277 template< typename StreamT >
278 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::openmode stream_ref< StreamT >::binary;
279 template< typename StreamT >
280 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::openmode stream_ref< StreamT >::in;
281 template< typename StreamT >
282 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::openmode stream_ref< StreamT >::out;
283 template< typename StreamT >
284 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::openmode stream_ref< StreamT >::trunc;
285 
286 template< typename StreamT >
287 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::seekdir stream_ref< StreamT >::beg;
288 template< typename StreamT >
289 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::seekdir stream_ref< StreamT >::cur;
290 template< typename StreamT >
291 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::seekdir stream_ref< StreamT >::end;
292 
293 template< typename StreamT >
294 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::event stream_ref< StreamT >::erase_event;
295 template< typename StreamT >
296 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::event stream_ref< StreamT >::imbue_event;
297 template< typename StreamT >
298 BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::event stream_ref< StreamT >::copyfmt_event;
299 
300 //! Default log record message formatter
301 struct message_formatter
302 {
303     typedef void result_type;
304 
message_formatterboost::expressions::aux::message_formatter305     message_formatter() : m_MessageName(expressions::tag::message::get_name())
306     {
307     }
308 
309     template< typename StreamT >
operator ()boost::expressions::aux::message_formatter310     BOOST_FORCEINLINE result_type operator() (record_view const& rec, StreamT& strm) const
311     {
312         boost::log::visit< expressions::tag::message::value_type >(m_MessageName, rec, boost::log::bind_output(strm));
313     }
314 
315 private:
316     const attribute_name m_MessageName;
317 };
318 
319 } // namespace aux
320 
321 } // namespace expressions
322 
323 /*!
324  * Log record formatter function wrapper.
325  */
326 template< typename CharT >
327 class basic_formatter
328 {
329     typedef basic_formatter this_type;
330     BOOST_COPYABLE_AND_MOVABLE(this_type)
331 
332 public:
333     //! Result type
334     typedef void result_type;
335 
336     //! Character type
337     typedef CharT char_type;
338     //! Output stream type
339     typedef basic_formatting_ostream< char_type > stream_type;
340 
341 private:
342     //! Filter function type
343     typedef boost::log::aux::light_function< void (record_view const&, expressions::aux::stream_ref< stream_type >) > formatter_type;
344 
345 private:
346     //! Formatter function
347     formatter_type m_Formatter;
348 
349 public:
350     /*!
351      * Default constructor. Creates a formatter that only outputs log message.
352      */
basic_formatter()353     basic_formatter() : m_Formatter(expressions::aux::message_formatter())
354     {
355     }
356     /*!
357      * Copy constructor
358      */
basic_formatter(basic_formatter const & that)359     basic_formatter(basic_formatter const& that) : m_Formatter(that.m_Formatter)
360     {
361     }
362     /*!
363      * Move constructor. The moved-from formatter is left in an unspecified state.
364      */
basic_formatter(BOOST_RV_REF (this_type)that)365     basic_formatter(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT : m_Formatter(boost::move(that.m_Formatter))
366     {
367     }
368 
369     /*!
370      * Initializing constructor. Creates a formatter which will invoke the specified function object.
371      */
372 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
373     template< typename FunT >
basic_formatter(FunT && fun)374     basic_formatter(FunT&& fun) : m_Formatter(boost::forward< FunT >(fun))
375     {
376     }
377 #elif !defined(BOOST_MSVC) || BOOST_MSVC >= 1600
378     template< typename FunT >
basic_formatter(FunT const & fun,typename boost::disable_if_c<move_detail::is_rv<FunT>::value,boost::log::aux::sfinae_dummy>::type=boost::log::aux::sfinae_dummy ())379     basic_formatter(FunT const& fun, typename boost::disable_if_c< move_detail::is_rv< FunT >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) : m_Formatter(fun)
380     {
381     }
382 #else
383     // MSVC 9 and older blows up in unexpected ways if we use SFINAE to disable constructor instantiation
384     template< typename FunT >
basic_formatter(FunT const & fun)385     basic_formatter(FunT const& fun) : m_Formatter(fun)
386     {
387     }
388     template< typename FunT >
basic_formatter(rv<FunT> & fun)389     basic_formatter(rv< FunT >& fun) : m_Formatter(fun)
390     {
391     }
392     template< typename FunT >
basic_formatter(rv<FunT> const & fun)393     basic_formatter(rv< FunT > const& fun) : m_Formatter(static_cast< FunT const& >(fun))
394     {
395     }
basic_formatter(rv<this_type> const & that)396     basic_formatter(rv< this_type > const& that) : m_Formatter(that.m_Formatter)
397     {
398     }
399 #endif
400 
401     /*!
402      * Move assignment. The moved-from formatter is left in an unspecified state.
403      */
operator =(BOOST_RV_REF (this_type)that)404     basic_formatter& operator= (BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT
405     {
406         m_Formatter.swap(that.m_Formatter);
407         return *this;
408     }
409     /*!
410      * Copy assignment.
411      */
operator =(BOOST_COPY_ASSIGN_REF (this_type)that)412     basic_formatter& operator= (BOOST_COPY_ASSIGN_REF(this_type) that)
413     {
414         m_Formatter = that.m_Formatter;
415         return *this;
416     }
417     /*!
418      * Initializing assignment. Sets the specified function object to the formatter.
419      */
420 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
421     template< typename FunT >
operator =(FunT && fun)422     basic_formatter& operator= (FunT&& fun)
423     {
424         this_type(boost::forward< FunT >(fun)).swap(*this);
425         return *this;
426     }
427 #else
428     template< typename FunT >
429     typename boost::disable_if_c< is_same< typename remove_cv< FunT >::type, this_type >::value, this_type& >::type
operator =(FunT const & fun)430     operator= (FunT const& fun)
431     {
432         this_type(fun).swap(*this);
433         return *this;
434     }
435 #endif
436 
437     /*!
438      * Formatting operator.
439      *
440      * \param rec A log record to format.
441      * \param strm A stream to put the formatted characters to.
442      */
operator ()(record_view const & rec,stream_type & strm) const443     result_type operator() (record_view const& rec, stream_type& strm) const
444     {
445         m_Formatter(rec, expressions::aux::stream_ref< stream_type >(strm));
446     }
447 
448     /*!
449      * Resets the formatter to the default. The default formatter only outputs message text.
450      */
reset()451     void reset()
452     {
453         m_Formatter = expressions::aux::message_formatter();
454     }
455 
456     /*!
457      * Swaps two formatters
458      */
swap(basic_formatter & that)459     void swap(basic_formatter& that) BOOST_NOEXCEPT
460     {
461         m_Formatter.swap(that.m_Formatter);
462     }
463 };
464 
465 template< typename CharT >
swap(basic_formatter<CharT> & left,basic_formatter<CharT> & right)466 inline void swap(basic_formatter< CharT >& left, basic_formatter< CharT >& right) BOOST_NOEXCEPT
467 {
468     left.swap(right);
469 }
470 
471 #ifdef BOOST_LOG_USE_CHAR
472 typedef basic_formatter< char > formatter;
473 #endif
474 #ifdef BOOST_LOG_USE_WCHAR_T
475 typedef basic_formatter< wchar_t > wformatter;
476 #endif
477 
478 BOOST_LOG_CLOSE_NAMESPACE // namespace log
479 
480 } // namespace boost
481 
482 #include <boost/log/detail/footer.hpp>
483 
484 #endif // BOOST_LOG_EXPRESSIONS_FORMATTER_HPP_INCLUDED_
485