Chris@102
|
1 // Copyright Kevlin Henney, 2000-2005.
|
Chris@102
|
2 // Copyright Alexander Nasonov, 2006-2010.
|
Chris@102
|
3 // Copyright Antony Polukhin, 2011-2014.
|
Chris@102
|
4 //
|
Chris@102
|
5 // Distributed under the Boost Software License, Version 1.0. (See
|
Chris@102
|
6 // accompanying file LICENSE_1_0.txt or copy at
|
Chris@102
|
7 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@102
|
8 //
|
Chris@102
|
9 // what: lexical_cast custom keyword cast
|
Chris@102
|
10 // who: contributed by Kevlin Henney,
|
Chris@102
|
11 // enhanced with contributions from Terje Slettebo,
|
Chris@102
|
12 // with additional fixes and suggestions from Gennaro Prota,
|
Chris@102
|
13 // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov,
|
Chris@102
|
14 // Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann,
|
Chris@102
|
15 // Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters
|
Chris@102
|
16 // when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2014
|
Chris@102
|
17
|
Chris@102
|
18 #ifndef BOOST_LEXICAL_CAST_TRY_LEXICAL_CONVERT_HPP
|
Chris@102
|
19 #define BOOST_LEXICAL_CAST_TRY_LEXICAL_CONVERT_HPP
|
Chris@102
|
20
|
Chris@102
|
21 #include <boost/config.hpp>
|
Chris@102
|
22 #ifdef BOOST_HAS_PRAGMA_ONCE
|
Chris@102
|
23 # pragma once
|
Chris@102
|
24 #endif
|
Chris@102
|
25
|
Chris@102
|
26 #include <string>
|
Chris@102
|
27 #include <boost/mpl/if.hpp>
|
Chris@102
|
28 #include <boost/type_traits/ice.hpp>
|
Chris@102
|
29 #include <boost/type_traits/is_same.hpp>
|
Chris@102
|
30 #include <boost/type_traits/is_arithmetic.hpp>
|
Chris@102
|
31
|
Chris@102
|
32 #include <boost/lexical_cast/detail/is_character.hpp>
|
Chris@102
|
33 #include <boost/lexical_cast/detail/converter_numeric.hpp>
|
Chris@102
|
34 #include <boost/lexical_cast/detail/converter_lexical.hpp>
|
Chris@102
|
35
|
Chris@102
|
36 #include <boost/range/iterator_range_core.hpp>
|
Chris@102
|
37 #include <boost/container/container_fwd.hpp>
|
Chris@102
|
38
|
Chris@102
|
39 namespace boost {
|
Chris@102
|
40 namespace detail
|
Chris@102
|
41 {
|
Chris@102
|
42 template<typename T>
|
Chris@102
|
43 struct is_stdstring
|
Chris@102
|
44 : boost::false_type
|
Chris@102
|
45 {};
|
Chris@102
|
46
|
Chris@102
|
47 template<typename CharT, typename Traits, typename Alloc>
|
Chris@102
|
48 struct is_stdstring< std::basic_string<CharT, Traits, Alloc> >
|
Chris@102
|
49 : boost::true_type
|
Chris@102
|
50 {};
|
Chris@102
|
51
|
Chris@102
|
52 template<typename CharT, typename Traits, typename Alloc>
|
Chris@102
|
53 struct is_stdstring< boost::container::basic_string<CharT, Traits, Alloc> >
|
Chris@102
|
54 : boost::true_type
|
Chris@102
|
55 {};
|
Chris@102
|
56
|
Chris@102
|
57 template<typename Target, typename Source>
|
Chris@102
|
58 struct is_arithmetic_and_not_xchars
|
Chris@102
|
59 {
|
Chris@102
|
60 BOOST_STATIC_CONSTANT(bool, value = (
|
Chris@102
|
61 boost::type_traits::ice_and<
|
Chris@102
|
62 boost::type_traits::ice_not<
|
Chris@102
|
63 boost::detail::is_character<Target>::value
|
Chris@102
|
64 >::value,
|
Chris@102
|
65 boost::type_traits::ice_not<
|
Chris@102
|
66 boost::detail::is_character<Source>::value
|
Chris@102
|
67 >::value,
|
Chris@102
|
68 boost::is_arithmetic<Source>::value,
|
Chris@102
|
69 boost::is_arithmetic<Target>::value
|
Chris@102
|
70 >::value
|
Chris@102
|
71 ));
|
Chris@102
|
72 };
|
Chris@102
|
73
|
Chris@102
|
74 /*
|
Chris@102
|
75 * is_xchar_to_xchar<Target, Source>::value is true,
|
Chris@102
|
76 * Target and Souce are char types of the same size 1 (char, signed char, unsigned char).
|
Chris@102
|
77 */
|
Chris@102
|
78 template<typename Target, typename Source>
|
Chris@102
|
79 struct is_xchar_to_xchar
|
Chris@102
|
80 {
|
Chris@102
|
81 BOOST_STATIC_CONSTANT(bool, value = (
|
Chris@102
|
82 boost::type_traits::ice_and<
|
Chris@102
|
83 boost::type_traits::ice_eq<sizeof(Source), sizeof(Target)>::value,
|
Chris@102
|
84 boost::type_traits::ice_eq<sizeof(Source), sizeof(char)>::value,
|
Chris@102
|
85 boost::detail::is_character<Target>::value,
|
Chris@102
|
86 boost::detail::is_character<Source>::value
|
Chris@102
|
87 >::value
|
Chris@102
|
88 ));
|
Chris@102
|
89 };
|
Chris@102
|
90
|
Chris@102
|
91 template<typename Target, typename Source>
|
Chris@102
|
92 struct is_char_array_to_stdstring
|
Chris@102
|
93 : boost::false_type
|
Chris@102
|
94 {};
|
Chris@102
|
95
|
Chris@102
|
96 template<typename CharT, typename Traits, typename Alloc>
|
Chris@102
|
97 struct is_char_array_to_stdstring< std::basic_string<CharT, Traits, Alloc>, CharT* >
|
Chris@102
|
98 : boost::true_type
|
Chris@102
|
99 {};
|
Chris@102
|
100
|
Chris@102
|
101 template<typename CharT, typename Traits, typename Alloc>
|
Chris@102
|
102 struct is_char_array_to_stdstring< std::basic_string<CharT, Traits, Alloc>, const CharT* >
|
Chris@102
|
103 : boost::true_type
|
Chris@102
|
104 {};
|
Chris@102
|
105
|
Chris@102
|
106 template<typename CharT, typename Traits, typename Alloc>
|
Chris@102
|
107 struct is_char_array_to_stdstring< boost::container::basic_string<CharT, Traits, Alloc>, CharT* >
|
Chris@102
|
108 : boost::true_type
|
Chris@102
|
109 {};
|
Chris@102
|
110
|
Chris@102
|
111 template<typename CharT, typename Traits, typename Alloc>
|
Chris@102
|
112 struct is_char_array_to_stdstring< boost::container::basic_string<CharT, Traits, Alloc>, const CharT* >
|
Chris@102
|
113 : boost::true_type
|
Chris@102
|
114 {};
|
Chris@102
|
115
|
Chris@102
|
116 template <typename Target, typename Source>
|
Chris@102
|
117 struct copy_converter_impl
|
Chris@102
|
118 {
|
Chris@102
|
119 // MSVC fail to forward an array (DevDiv#555157 "SILENT BAD CODEGEN triggered by perfect forwarding",
|
Chris@102
|
120 // fixed in 2013 RTM).
|
Chris@102
|
121 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && (!defined(BOOST_MSVC) || BOOST_MSVC >= 1800)
|
Chris@102
|
122 template <class T>
|
Chris@102
|
123 static inline bool try_convert(T&& arg, Target& result) {
|
Chris@102
|
124 result = static_cast<T&&>(arg); // eqaul to `result = std::forward<T>(arg);`
|
Chris@102
|
125 return true;
|
Chris@102
|
126 }
|
Chris@102
|
127 #else
|
Chris@102
|
128 static inline bool try_convert(const Source& arg, Target& result) {
|
Chris@102
|
129 result = arg;
|
Chris@102
|
130 return true;
|
Chris@102
|
131 }
|
Chris@102
|
132 #endif
|
Chris@102
|
133 };
|
Chris@102
|
134 }
|
Chris@102
|
135
|
Chris@102
|
136 namespace conversion { namespace detail {
|
Chris@102
|
137
|
Chris@102
|
138 template <typename Target, typename Source>
|
Chris@102
|
139 inline bool try_lexical_convert(const Source& arg, Target& result)
|
Chris@102
|
140 {
|
Chris@102
|
141 typedef BOOST_DEDUCED_TYPENAME boost::detail::array_to_pointer_decay<Source>::type src;
|
Chris@102
|
142
|
Chris@102
|
143 typedef BOOST_DEDUCED_TYPENAME boost::type_traits::ice_or<
|
Chris@102
|
144 boost::detail::is_xchar_to_xchar<Target, src >::value,
|
Chris@102
|
145 boost::detail::is_char_array_to_stdstring<Target, src >::value,
|
Chris@102
|
146 boost::type_traits::ice_and<
|
Chris@102
|
147 boost::is_same<Target, src >::value,
|
Chris@102
|
148 boost::detail::is_stdstring<Target >::value
|
Chris@102
|
149 >::value,
|
Chris@102
|
150 boost::type_traits::ice_and<
|
Chris@102
|
151 boost::is_same<Target, src >::value,
|
Chris@102
|
152 boost::detail::is_character<Target >::value
|
Chris@102
|
153 >::value
|
Chris@102
|
154 > shall_we_copy_t;
|
Chris@102
|
155
|
Chris@102
|
156 typedef boost::detail::is_arithmetic_and_not_xchars<Target, src >
|
Chris@102
|
157 shall_we_copy_with_dynamic_check_t;
|
Chris@102
|
158
|
Chris@102
|
159 // We do evaluate second `if_` lazily to avoid unnecessary instantiations
|
Chris@102
|
160 // of `shall_we_copy_with_dynamic_check_t` and improve compilation times.
|
Chris@102
|
161 typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
|
Chris@102
|
162 shall_we_copy_t::value,
|
Chris@102
|
163 boost::mpl::identity<boost::detail::copy_converter_impl<Target, src > >,
|
Chris@102
|
164 boost::mpl::if_<
|
Chris@102
|
165 shall_we_copy_with_dynamic_check_t,
|
Chris@102
|
166 boost::detail::dynamic_num_converter_impl<Target, src >,
|
Chris@102
|
167 boost::detail::lexical_converter_impl<Target, src >
|
Chris@102
|
168 >
|
Chris@102
|
169 >::type caster_type_lazy;
|
Chris@102
|
170
|
Chris@102
|
171 typedef BOOST_DEDUCED_TYPENAME caster_type_lazy::type caster_type;
|
Chris@102
|
172
|
Chris@102
|
173 return caster_type::try_convert(arg, result);
|
Chris@102
|
174 }
|
Chris@102
|
175
|
Chris@102
|
176 template <typename Target, typename CharacterT>
|
Chris@102
|
177 inline bool try_lexical_convert(const CharacterT* chars, std::size_t count, Target& result)
|
Chris@102
|
178 {
|
Chris@102
|
179 BOOST_STATIC_ASSERT_MSG(
|
Chris@102
|
180 boost::detail::is_character<CharacterT>::value,
|
Chris@102
|
181 "This overload of try_lexical_convert is meant to be used only with arrays of characters."
|
Chris@102
|
182 );
|
Chris@102
|
183 return ::boost::conversion::detail::try_lexical_convert(
|
Chris@102
|
184 ::boost::iterator_range<const CharacterT*>(chars, chars + count), result
|
Chris@102
|
185 );
|
Chris@102
|
186 }
|
Chris@102
|
187
|
Chris@102
|
188 }} // namespace conversion::detail
|
Chris@102
|
189
|
Chris@102
|
190 namespace conversion {
|
Chris@102
|
191 // ADL barrier
|
Chris@102
|
192 using ::boost::conversion::detail::try_lexical_convert;
|
Chris@102
|
193 }
|
Chris@102
|
194
|
Chris@102
|
195 } // namespace boost
|
Chris@102
|
196
|
Chris@102
|
197 #endif // BOOST_LEXICAL_CAST_TRY_LEXICAL_CONVERT_HPP
|
Chris@102
|
198
|