]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 add_value.hpp | |
9 | * \author Andrey Semashev | |
10 | * \date 26.11.2012 | |
11 | * | |
12 | * This header contains the \c add_value manipulator. | |
13 | */ | |
14 | ||
15 | #ifndef BOOST_LOG_UTILITY_MANIPULATORS_ADD_VALUE_HPP_INCLUDED_ | |
16 | #define BOOST_LOG_UTILITY_MANIPULATORS_ADD_VALUE_HPP_INCLUDED_ | |
17 | ||
18 | #include <boost/mpl/if.hpp> | |
19 | #include <boost/type_traits/is_scalar.hpp> | |
20 | #include <boost/type_traits/remove_cv.hpp> | |
21 | #include <boost/type_traits/remove_reference.hpp> | |
22 | #include <boost/log/detail/config.hpp> | |
23 | #include <boost/log/detail/embedded_string_type.hpp> | |
24 | #include <boost/log/attributes/attribute_name.hpp> | |
25 | #include <boost/log/attributes/attribute_value_impl.hpp> | |
26 | #include <boost/log/expressions/keyword_fwd.hpp> | |
27 | #include <boost/log/sources/record_ostream.hpp> | |
28 | #include <boost/log/detail/header.hpp> | |
29 | ||
30 | #ifdef BOOST_HAS_PRAGMA_ONCE | |
31 | #pragma once | |
32 | #endif | |
33 | ||
34 | #ifdef _MSC_VER | |
35 | #pragma warning(push) | |
36 | // 'boost::log::v2s_mt_nt6::add_value_manip<RefT>::m_value' : reference member is initialized to a temporary that doesn't persist after the constructor exits | |
37 | // This is intentional since the manipulator can be used with a temporary, which will be used before the streaming expression ends and it is destroyed. | |
38 | #pragma warning(disable: 4413) | |
39 | // returning address of local variable or temporary | |
40 | // This warning refers to add_value_manip<RefT>::get_value() when RefT is an rvalue reference. We store the reference in the manipulator and we intend to return it as is. | |
41 | #pragma warning(disable: 4172) | |
42 | #endif | |
43 | ||
44 | namespace boost { | |
45 | ||
46 | BOOST_LOG_OPEN_NAMESPACE | |
47 | ||
48 | //! Attribute value manipulator | |
49 | template< typename RefT > | |
50 | class add_value_manip | |
51 | { | |
52 | public: | |
53 | //! Stored reference type | |
54 | typedef RefT reference_type; | |
55 | //! Attribute value type | |
56 | typedef typename remove_cv< typename remove_reference< reference_type >::type >::type value_type; | |
57 | ||
58 | private: | |
59 | // The stored reference type is an lvalue reference since apparently different compilers (GCC and MSVC) have different quirks when rvalue references are stored as members. | |
60 | // Additionally, MSVC (at least 11.0) has a bug which causes a dangling reference to be stored in the manipulator, if a scalar rvalue is passed to the add_value generator. | |
61 | // To work around this problem we save the value inside the manipulator in this case. | |
62 | typedef typename remove_reference< reference_type >::type& lvalue_reference_type; | |
63 | ||
64 | typedef typename mpl::if_< | |
65 | is_scalar< value_type >, | |
66 | value_type, | |
67 | lvalue_reference_type | |
68 | >::type stored_type; | |
69 | ||
70 | typedef typename mpl::if_< | |
71 | is_scalar< value_type >, | |
72 | value_type, | |
73 | reference_type | |
74 | >::type get_value_result_type; | |
75 | ||
76 | private: | |
77 | //! Attribute value | |
78 | stored_type m_value; | |
79 | //! Attribute name | |
80 | attribute_name m_name; | |
81 | ||
82 | public: | |
83 | //! Initializing constructor | |
84 | add_value_manip(attribute_name const& name, reference_type value) : m_value(static_cast< lvalue_reference_type >(value)), m_name(name) | |
85 | { | |
86 | } | |
87 | ||
88 | //! Returns attribute name | |
89 | attribute_name get_name() const { return m_name; } | |
90 | //! Returns attribute value | |
91 | get_value_result_type get_value() const { return static_cast< get_value_result_type >(m_value); } | |
92 | }; | |
93 | ||
94 | //! The operator attaches an attribute value to the log record | |
95 | template< typename CharT, typename RefT > | |
96 | inline basic_record_ostream< CharT >& operator<< (basic_record_ostream< CharT >& strm, add_value_manip< RefT > const& manip) | |
97 | { | |
98 | typedef typename aux::make_embedded_string_type< typename add_value_manip< RefT >::value_type >::type value_type; | |
99 | attribute_value value(new attributes::attribute_value_impl< value_type >(manip.get_value())); | |
100 | strm.get_record().attribute_values().insert(manip.get_name(), value); | |
101 | return strm; | |
102 | } | |
103 | ||
104 | //! The function creates a manipulator that attaches an attribute value to a log record | |
105 | #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) | |
106 | ||
107 | template< typename T > | |
108 | inline add_value_manip< T&& > add_value(attribute_name const& name, T&& value) | |
109 | { | |
110 | return add_value_manip< T&& >(name, static_cast< T&& >(value)); | |
111 | } | |
112 | ||
113 | //! \overload | |
114 | template< typename DescriptorT, template< typename > class ActorT > | |
115 | inline add_value_manip< typename DescriptorT::value_type&& > | |
116 | add_value(expressions::attribute_keyword< DescriptorT, ActorT > const&, typename DescriptorT::value_type&& value) | |
117 | { | |
118 | typedef typename DescriptorT::value_type value_type; | |
119 | return add_value_manip< value_type&& >(DescriptorT::get_name(), static_cast< value_type&& >(value)); | |
120 | } | |
121 | ||
122 | //! \overload | |
123 | template< typename DescriptorT, template< typename > class ActorT > | |
124 | inline add_value_manip< typename DescriptorT::value_type& > | |
125 | add_value(expressions::attribute_keyword< DescriptorT, ActorT > const&, typename DescriptorT::value_type& value) | |
126 | { | |
127 | return add_value_manip< typename DescriptorT::value_type& >(DescriptorT::get_name(), value); | |
128 | } | |
129 | ||
130 | //! \overload | |
131 | template< typename DescriptorT, template< typename > class ActorT > | |
132 | inline add_value_manip< typename DescriptorT::value_type const& > | |
133 | add_value(expressions::attribute_keyword< DescriptorT, ActorT > const&, typename DescriptorT::value_type const& value) | |
134 | { | |
135 | return add_value_manip< typename DescriptorT::value_type const& >(DescriptorT::get_name(), value); | |
136 | } | |
137 | ||
138 | #else // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) | |
139 | ||
140 | template< typename T > | |
141 | inline add_value_manip< T const& > add_value(attribute_name const& name, T const& value) | |
142 | { | |
143 | return add_value_manip< T const& >(name, value); | |
144 | } | |
145 | ||
146 | template< typename DescriptorT, template< typename > class ActorT > | |
147 | inline add_value_manip< typename DescriptorT::value_type const& > | |
148 | add_value(expressions::attribute_keyword< DescriptorT, ActorT > const&, typename DescriptorT::value_type const& value) | |
149 | { | |
150 | return add_value_manip< typename DescriptorT::value_type const& >(DescriptorT::get_name(), value); | |
151 | } | |
152 | ||
153 | #endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) | |
154 | ||
155 | BOOST_LOG_CLOSE_NAMESPACE // namespace log | |
156 | ||
157 | } // namespace boost | |
158 | ||
159 | #ifdef _MSC_VER | |
160 | #pragma warning(pop) | |
161 | #endif | |
162 | ||
163 | #include <boost/log/detail/footer.hpp> | |
164 | ||
165 | #endif // BOOST_LOG_UTILITY_MANIPULATORS_ADD_VALUE_HPP_INCLUDED_ |