Stream type detection metafunctions were rewritten so that now they can detect stream type for user defined types (refs #6786)

Removed unrequired `::` 

[SVN r81278]
This commit is contained in:
Antony Polukhin
2012-11-10 07:42:04 +00:00
parent 5c3159cd1c
commit 1c37887f2b
3 changed files with 627 additions and 257 deletions

View File

@@ -162,6 +162,8 @@ namespace boost
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/type_traits/has_left_shift.hpp>
#include <boost/type_traits/has_right_shift.hpp>
#include <boost/math/special_functions/sign.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/range/iterator_range_core.hpp>
@@ -171,236 +173,331 @@ namespace boost
#endif
namespace boost {
namespace detail // widest_char<...> (continuation)
{
struct not_a_character_type{};
template <typename CharT>
struct widest_char<not_a_character_type, CharT >
{
typedef CharT type;
};
template <typename CharT>
struct widest_char< CharT, not_a_character_type >
{
typedef CharT type;
};
template <>
struct widest_char< not_a_character_type, not_a_character_type >
{
typedef char type;
};
}
namespace detail // is_char_or_wchar<...> and stream_char<...> templates
namespace detail // is_char_or_wchar<...>
{
// returns true, if T is one of the character types
template <typename T>
template < typename T >
struct is_char_or_wchar
{
typedef ::boost::type_traits::ice_or<
::boost::is_same< T, char >::value,
typedef boost::type_traits::ice_or<
boost::is_same< T, char >::value,
#ifndef BOOST_LCAST_NO_WCHAR_T
::boost::is_same< T, wchar_t >::value,
boost::is_same< T, wchar_t >::value,
#endif
#ifndef BOOST_NO_CHAR16_T
::boost::is_same< T, char16_t >::value,
boost::is_same< T, char16_t >::value,
#endif
#ifndef BOOST_NO_CHAR32_T
::boost::is_same< T, char32_t >::value,
boost::is_same< T, char32_t >::value,
#endif
::boost::is_same< T, unsigned char >::value,
::boost::is_same< T, signed char >::value
boost::is_same< T, unsigned char >::value,
boost::is_same< T, signed char >::value
> result_type;
BOOST_STATIC_CONSTANT(bool, value = (result_type::value) );
};
}
// selectors for choosing stream character type
// returns one of char, wchar_t, char16_t, char32_t or not_a_character_type types
template <typename Type>
struct stream_char
namespace detail // normalize_single_byte_char<Char>
{
// Converts signed/unsigned char to char
template < class Char >
struct normalize_single_byte_char
{
typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
is_char_or_wchar<Type >::value,
Type,
boost::detail::not_a_character_type
>::type type;
typedef Char type;
};
template <>
struct stream_char<unsigned char>
struct normalize_single_byte_char< signed char >
{
typedef char type;
};
template <>
struct stream_char<signed char>
struct normalize_single_byte_char< unsigned char >
{
typedef char type;
};
}
template <typename CharT>
struct stream_char<CharT*>
{
typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type;
};
namespace detail // deduce_character_type_later<T>
{
// Helper type, meaning that stram character for T must be deduced
// at Stage 2 (See deduce_source_char<T> and deduce_target_char<T>)
template < class T > struct deduce_character_type_later {};
}
template <typename CharT>
struct stream_char<const CharT*>
{
typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type;
};
namespace detail // stream_char_common<T>
{
// Selectors to choose stream character type (common for Source and Target)
// Returns one of char, wchar_t, char16_t, char32_t or deduce_character_type_later<T> types
// Executed on Stage 1 (See deduce_source_char<T> and deduce_target_char<T>)
template < typename Type >
struct stream_char_common: public boost::mpl::if_c<
boost::detail::is_char_or_wchar< Type >::value,
Type,
boost::detail::deduce_character_type_later< Type >
> {};
template <typename CharT>
struct stream_char<iterator_range<CharT*> >
{
typedef BOOST_DEDUCED_TYPENAME stream_char<CharT*>::type type;
};
template < typename Char >
struct stream_char_common< Char* >: public boost::mpl::if_c<
boost::detail::is_char_or_wchar< Char >::value,
Char,
boost::detail::deduce_character_type_later< Char* >
> {};
template < typename Char >
struct stream_char_common< const Char* >: public boost::mpl::if_c<
boost::detail::is_char_or_wchar< Char >::value,
Char,
boost::detail::deduce_character_type_later< const Char* >
> {};
template < typename Char >
struct stream_char_common< boost::iterator_range< Char* > >: public boost::mpl::if_c<
boost::detail::is_char_or_wchar< Char >::value,
Char,
boost::detail::deduce_character_type_later< boost::iterator_range< Char* > >
> {};
template <typename CharT>
struct stream_char<iterator_range<const CharT*> >
template < typename Char >
struct stream_char_common< boost::iterator_range< const Char* > >: public boost::mpl::if_c<
boost::detail::is_char_or_wchar< Char >::value,
Char,
boost::detail::deduce_character_type_later< boost::iterator_range< const Char* > >
> {};
template < class Char, class Traits, class Alloc >
struct stream_char_common< std::basic_string< Char, Traits, Alloc > >
{
typedef BOOST_DEDUCED_TYPENAME stream_char<const CharT*>::type type;
typedef Char type;
};
template <class CharT, class Traits, class Alloc>
struct stream_char< std::basic_string<CharT, Traits, Alloc> >
template < class Char, class Traits, class Alloc >
struct stream_char_common< boost::container::basic_string< Char, Traits, Alloc > >
{
typedef CharT type;
typedef Char type;
};
template <class CharT, class Traits, class Alloc>
struct stream_char< ::boost::container::basic_string<CharT, Traits, Alloc> >
{
typedef CharT type;
};
template < typename Char, std::size_t N >
struct stream_char_common< boost::array< Char, N > >: public boost::mpl::if_c<
boost::detail::is_char_or_wchar< Char >::value,
Char,
boost::detail::deduce_character_type_later< boost::array< Char, N > >
> {};
template<typename CharT, std::size_t N>
struct stream_char<boost::array<CharT, N> >
{
typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type;
};
template<typename CharT, std::size_t N>
struct stream_char<boost::array<const CharT, N> >
{
typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type;
};
template < typename Char, std::size_t N >
struct stream_char_common< boost::array< const Char, N > >: public boost::mpl::if_c<
boost::detail::is_char_or_wchar< Char >::value,
Char,
boost::detail::deduce_character_type_later< boost::array< const Char, N > >
> {};
#if !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY)
template <typename CharT, std::size_t N>
struct stream_char<std::array<CharT, N> >
{
typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type;
};
template < typename Char, std::size_t N >
struct stream_char_common< std::array<Char, N > >: public boost::mpl::if_c<
boost::detail::is_char_or_wchar< Char >::value,
Char,
boost::detail::deduce_character_type_later< std::array< Char, N > >
> {};
template <typename CharT, std::size_t N>
struct stream_char<std::array<const CharT, N> >
{
typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type;
};
template < typename Char, std::size_t N >
struct stream_char_common< std::array< const Char, N > >: public boost::mpl::if_c<
boost::detail::is_char_or_wchar< Char >::value,
Char,
boost::detail::deduce_character_type_later< std::array< const Char, N > >
> {};
#endif // !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY)
#if !defined(BOOST_LCAST_NO_WCHAR_T) && defined(BOOST_NO_INTRINSIC_WCHAR_T)
template<>
struct stream_char<wchar_t>
template <>
struct stream_char_common< wchar_t >
{
typedef boost::detail::not_a_character_type type;
};
template<>
struct stream_char<wchar_t*>
{
typedef wchar_t type;
};
template<>
struct stream_char<const wchar_t*>
{
typedef wchar_t type;
typedef char type;
};
#endif
}
namespace detail // deduce_source_char_impl<T>
{
// If type T is `deduce_character_type_later` type, then tries to deduce
// character type using boost::has_left_shift<T> metafunction.
// Otherwise supplied type T is a character type, that must be normalized
// using normalize_single_byte_char<Char>.
// Executed at Stage 2 (See deduce_source_char<T> and deduce_target_char<T>)
template < class Char >
struct deduce_source_char_impl
{
typedef BOOST_DEDUCED_TYPENAME boost::detail::normalize_single_byte_char< Char >::type type;
};
template < class T >
struct deduce_source_char_impl< deduce_character_type_later< T > >
{
typedef boost::has_left_shift< std::basic_ostream< char >, T > result_t;
#if defined(BOOST_LCAST_NO_WCHAR_T)
BOOST_STATIC_ASSERT_MSG((result_t::value),
"Source type is not std::ostream`able and std::wostream`s are not supported by your STL implementation");
typedef char type;
#else
typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
result_t::value, char, wchar_t
>::type type;
BOOST_STATIC_ASSERT_MSG((result_t::value || boost::has_left_shift< std::basic_ostream< type >, T >::value),
"Source type is neither std::ostream`able nor std::wostream`able");
#endif
};
}
namespace detail // deduce_target_char_impl<T>
{
// If type T is `deduce_character_type_later` type, then tries to deduce
// character type using boost::has_right_shift<T> metafunction.
// Otherwise supplied type T is a character type, that must be normalized
// using normalize_single_byte_char<Char>.
// Executed at Stage 2 (See deduce_source_char<T> and deduce_target_char<T>)
template < class Char >
struct deduce_target_char_impl
{
typedef BOOST_DEDUCED_TYPENAME normalize_single_byte_char< Char >::type type;
};
template < class T >
struct deduce_target_char_impl< deduce_character_type_later<T> >
{
typedef boost::has_right_shift<std::basic_istream<char>, T > result_t;
#if defined(BOOST_LCAST_NO_WCHAR_T)
BOOST_STATIC_ASSERT_MSG((result_t::value),
"Target type is not std::istream`able and std::wistream`s are not supported by your STL implementation");
typedef char type;
#else
typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
result_t::value, char, wchar_t
>::type type;
BOOST_STATIC_ASSERT_MSG((result_t::value || boost::has_right_shift<std::basic_istream<wchar_t>, T >::value),
"Target type is neither std::istream`able nor std::wistream`able");
#endif
};
}
namespace detail // deduce_target_char<T> and deduce_source_char<T>
{
// We deduce stream character types in two stages.
//
// Stage 1 is common for Target and Source. At Stage 1 we get
// non normalized character type (may contain unsigned/signed char)
// or deduce_character_type_later<T> where T is the original type.
// Stage 1 is executed by stream_char_common<T>
//
// At Stage 2 we normalize character types or try to deduce character
// type using metafunctions.
// Stage 2 is executed by deduce_target_char_impl<T> and
// deduce_source_char_impl<T>
//
// deduce_target_char<T> and deduce_source_char<T> functions combine
// both stages
template < class T >
struct deduce_target_char
{
typedef BOOST_DEDUCED_TYPENAME stream_char_common< T >::type stage1_type;
typedef BOOST_DEDUCED_TYPENAME deduce_target_char_impl< stage1_type >::type stage2_type;
typedef stage2_type type;
};
template < class T >
struct deduce_source_char
{
typedef BOOST_DEDUCED_TYPENAME stream_char_common< T >::type stage1_type;
typedef BOOST_DEDUCED_TYPENAME deduce_source_char_impl< stage1_type >::type stage2_type;
typedef stage2_type type;
};
}
namespace detail // deduce_char_traits template
{
template<class CharT, class Target, class Source>
// We are attempting to get char_traits<> from Source or Tagret
// template parameter. Otherwise we'll be using std::char_traits<Char>
template < class Char, class Target, class Source >
struct deduce_char_traits
{
typedef std::char_traits<CharT> type;
typedef std::char_traits< Char > type;
};
template<class CharT, class Traits, class Alloc, class Source>
struct deduce_char_traits< CharT
, std::basic_string<CharT,Traits,Alloc>
template < class Char, class Traits, class Alloc, class Source >
struct deduce_char_traits< Char
, std::basic_string< Char, Traits, Alloc >
, Source
>
{
typedef Traits type;
};
template<class CharT, class Target, class Traits, class Alloc>
struct deduce_char_traits< CharT
template < class Char, class Target, class Traits, class Alloc >
struct deduce_char_traits< Char
, Target
, std::basic_string<CharT,Traits,Alloc>
, std::basic_string< Char, Traits, Alloc >
>
{
typedef Traits type;
};
template<class CharT, class Traits, class Alloc, class Source>
struct deduce_char_traits< CharT
, ::boost::container::basic_string<CharT,Traits,Alloc>
template < class Char, class Traits, class Alloc, class Source >
struct deduce_char_traits< Char
, boost::container::basic_string< Char, Traits, Alloc >
, Source
>
{
typedef Traits type;
};
template<class CharT, class Target, class Traits, class Alloc>
struct deduce_char_traits< CharT
template < class Char, class Target, class Traits, class Alloc >
struct deduce_char_traits< Char
, Target
, ::boost::container::basic_string<CharT,Traits,Alloc>
, boost::container::basic_string< Char, Traits, Alloc >
>
{
typedef Traits type;
};
template<class CharT, class Traits, class Alloc1, class Alloc2>
struct deduce_char_traits< CharT
, std::basic_string<CharT,Traits,Alloc1>
, std::basic_string<CharT,Traits,Alloc2>
template < class Char, class Traits, class Alloc1, class Alloc2 >
struct deduce_char_traits< Char
, std::basic_string< Char, Traits, Alloc1 >
, std::basic_string< Char, Traits, Alloc2 >
>
{
typedef Traits type;
};
template<class CharT, class Traits, class Alloc1, class Alloc2>
struct deduce_char_traits< CharT
, ::boost::container::basic_string<CharT,Traits,Alloc1>
, ::boost::container::basic_string<CharT,Traits,Alloc2>
template<class Char, class Traits, class Alloc1, class Alloc2>
struct deduce_char_traits< Char
, boost::container::basic_string< Char, Traits, Alloc1 >
, boost::container::basic_string< Char, Traits, Alloc2 >
>
{
typedef Traits type;
};
template<class CharT, class Traits, class Alloc1, class Alloc2>
struct deduce_char_traits< CharT
, ::boost::container::basic_string<CharT,Traits,Alloc1>
, ::std::basic_string<CharT,Traits,Alloc2>
template < class Char, class Traits, class Alloc1, class Alloc2 >
struct deduce_char_traits< Char
, boost::container::basic_string< Char, Traits, Alloc1 >
, std::basic_string< Char, Traits, Alloc2 >
>
{
typedef Traits type;
};
template<class CharT, class Traits, class Alloc1, class Alloc2>
struct deduce_char_traits< CharT
, ::std::basic_string<CharT,Traits,Alloc1>
, ::boost::container::basic_string<CharT,Traits,Alloc2>
template < class Char, class Traits, class Alloc1, class Alloc2 >
struct deduce_char_traits< Char
, std::basic_string< Char, Traits, Alloc1 >
, boost::container::basic_string< Char, Traits, Alloc2 >
>
{
typedef Traits type;
@@ -518,7 +615,7 @@ namespace boost {
namespace detail // '0', '+' and '-' constants
{
template<typename CharT> struct lcast_char_constants;
template < typename Char > struct lcast_char_constants;
template<>
struct lcast_char_constants<char>
@@ -1247,7 +1344,7 @@ namespace boost {
typedef std::basic_ostringstream<CharT, Traits> out_stream_t;
typedef stl_buf_unlocker<std::basic_stringbuf<CharT, Traits>, CharT> unlocked_but_t;
#endif
typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c<
typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
RequiresStringbuffer,
out_stream_t,
do_not_construct_out_stream_t
@@ -1288,7 +1385,7 @@ namespace boost {
std::locale loc;
CharT const w = BOOST_USE_FACET(std::ctype<CharT>, loc).widen(ch);
#else
CharT const w = ch;
CharT const w = static_cast<CharT>(ch);
#endif
Traits::assign(*start, w);
finish = start + 1;
@@ -1439,7 +1536,7 @@ namespace boost {
}
template<class Alloc>
bool operator<<(::boost::container::basic_string<CharT,Traits,Alloc> const& str) BOOST_NOEXCEPT
bool operator<<(boost::container::basic_string<CharT,Traits,Alloc> const& str) BOOST_NOEXCEPT
{
start = const_cast<CharT*>(str.data());
finish = start + str.length();
@@ -1777,7 +1874,7 @@ namespace boost {
bool operator>>(std::basic_string<CharT,Traits,Alloc>& str) { str.assign(start, finish); return true; }
template<class Alloc>
bool operator>>(::boost::container::basic_string<CharT,Traits,Alloc>& str) { str.assign(start, finish); return true; }
bool operator>>(boost::container::basic_string<CharT,Traits,Alloc>& str) { str.assign(start, finish); return true; }
private:
@@ -1917,7 +2014,7 @@ namespace boost {
* */
boost::mpl::if_c<
#if defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64)
::boost::type_traits::ice_eq< sizeof(double), sizeof(long double) >::value,
boost::type_traits::ice_eq< sizeof(double), sizeof(long double) >::value,
#else
0
#endif
@@ -1968,7 +2065,7 @@ namespace boost {
};
template<typename CharT, typename Traits, typename Alloc>
struct is_stdstring< ::boost::container::basic_string<CharT, Traits, Alloc> >
struct is_stdstring< boost::container::basic_string<CharT, Traits, Alloc> >
{
BOOST_STATIC_CONSTANT(bool, value = true );
};
@@ -1978,13 +2075,13 @@ namespace boost {
{
BOOST_STATIC_CONSTANT(bool, value =
(
::boost::type_traits::ice_and<
::boost::is_arithmetic<Source>::value,
::boost::is_arithmetic<Target>::value,
::boost::type_traits::ice_not<
boost::type_traits::ice_and<
boost::is_arithmetic<Source>::value,
boost::is_arithmetic<Target>::value,
boost::type_traits::ice_not<
detail::is_char_or_wchar<Target>::value
>::value,
::boost::type_traits::ice_not<
boost::type_traits::ice_not<
detail::is_char_or_wchar<Source>::value
>::value
>::value
@@ -2002,14 +2099,14 @@ namespace boost {
{
BOOST_STATIC_CONSTANT(bool, value =
(
::boost::type_traits::ice_or<
::boost::type_traits::ice_and<
boost::type_traits::ice_or<
boost::type_traits::ice_and<
is_same<Source,Target>::value,
is_char_or_wchar<Target>::value
>::value,
::boost::type_traits::ice_and<
::boost::type_traits::ice_eq< sizeof(char),sizeof(Target)>::value,
::boost::type_traits::ice_eq< sizeof(char),sizeof(Source)>::value,
boost::type_traits::ice_and<
boost::type_traits::ice_eq< sizeof(char),sizeof(Target)>::value,
boost::type_traits::ice_eq< sizeof(char),sizeof(Source)>::value,
is_char_or_wchar<Target>::value,
is_char_or_wchar<Source>::value
>::value
@@ -2025,15 +2122,15 @@ namespace boost {
template <typename Float, typename Char>
struct is_this_float_conversion_optimized
{
typedef ::boost::type_traits::ice_and<
::boost::is_float<Float>::value,
typedef boost::type_traits::ice_and<
boost::is_float<Float>::value,
#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_SWPRINTF) && !defined(__MINGW32__)
::boost::type_traits::ice_or<
::boost::type_traits::ice_eq<sizeof(Char), sizeof(char) >::value,
::boost::is_same<Char, wchar_t>::value
boost::type_traits::ice_or<
boost::type_traits::ice_eq<sizeof(Char), sizeof(char) >::value,
boost::is_same<Char, wchar_t>::value
>::value
#else
::boost::type_traits::ice_eq<sizeof(Char), sizeof(char) >::value
boost::type_traits::ice_eq<sizeof(Char), sizeof(char) >::value
#endif
> result_type;
@@ -2059,13 +2156,13 @@ namespace boost {
};
template<typename CharT, typename Traits, typename Alloc>
struct is_char_array_to_stdstring< ::boost::container::basic_string<CharT, Traits, Alloc>, CharT* >
struct is_char_array_to_stdstring< boost::container::basic_string<CharT, Traits, Alloc>, CharT* >
{
BOOST_STATIC_CONSTANT(bool, value = true );
};
template<typename CharT, typename Traits, typename Alloc>
struct is_char_array_to_stdstring< ::boost::container::basic_string<CharT, Traits, Alloc>, const CharT* >
struct is_char_array_to_stdstring< boost::container::basic_string<CharT, Traits, Alloc>, const CharT* >
{
BOOST_STATIC_CONSTANT(bool, value = true );
};
@@ -2081,51 +2178,58 @@ namespace boost {
{
static inline Target lexical_cast_impl(const Source& arg)
{
typedef BOOST_DEDUCED_TYPENAME detail::array_to_pointer_decay<Source>::type src;
typedef BOOST_DEDUCED_TYPENAME ::boost::remove_cv<src>::type no_cv_src;
typedef BOOST_DEDUCED_TYPENAME detail::stream_char<Target>::type target_char_t;
typedef BOOST_DEDUCED_TYPENAME detail::stream_char<no_cv_src>::type src_char_type;
typedef BOOST_DEDUCED_TYPENAME detail::widest_char<
target_char_t, src_char_type
typedef BOOST_DEDUCED_TYPENAME boost::detail::array_to_pointer_decay<Source>::type src;
typedef BOOST_DEDUCED_TYPENAME boost::remove_cv<src>::type no_cv_src;
typedef boost::detail::deduce_source_char<no_cv_src> deduce_src_char_metafunc;
typedef BOOST_DEDUCED_TYPENAME deduce_src_char_metafunc::type src_char_t;
typedef BOOST_DEDUCED_TYPENAME boost::detail::deduce_target_char<Target>::type target_char_t;
typedef BOOST_DEDUCED_TYPENAME boost::detail::widest_char<
target_char_t, src_char_t
>::type char_type;
#if !defined(BOOST_NO_CHAR16_T) && defined(BOOST_NO_UNICODE_LITERALS)
BOOST_STATIC_ASSERT_MSG(( !::boost::is_same<char16_t, src_char_type>::value
&& !::boost::is_same<char16_t, target_char_t>::value),
BOOST_STATIC_ASSERT_MSG(( !boost::is_same<char16_t, src_char_t>::value
&& !boost::is_same<char16_t, target_char_t>::value),
"Your compiler does not have full support for char16_t" );
#endif
#if !defined(BOOST_NO_CHAR32_T) && defined(BOOST_NO_UNICODE_LITERALS)
BOOST_STATIC_ASSERT_MSG(( !::boost::is_same<char32_t, src_char_type>::value
&& !::boost::is_same<char32_t, target_char_t>::value),
BOOST_STATIC_ASSERT_MSG(( !boost::is_same<char32_t, src_char_t>::value
&& !boost::is_same<char32_t, target_char_t>::value),
"Your compiler does not have full support for char32_t" );
#endif
typedef BOOST_DEDUCED_TYPENAME ::boost::detail::deduce_char_traits<
typedef BOOST_DEDUCED_TYPENAME boost::detail::deduce_char_traits<
char_type, Target, no_cv_src
>::type traits;
typedef ::boost::type_traits::ice_and<
::boost::detail::is_char_or_wchar<src_char_type>::value, // source is lexical type
::boost::detail::is_char_or_wchar<target_char_t>::value, // target is a lexical type
::boost::is_same<char, src_char_type>::value, // source is not a wide character based type
::boost::type_traits::ice_ne<sizeof(char), sizeof(target_char_t) >::value // target type is based on wide character
typedef boost::type_traits::ice_and<
boost::is_same<char, src_char_t>::value, // source is not a wide character based type
boost::type_traits::ice_ne<sizeof(char), sizeof(target_char_t) >::value, // target type is based on wide character
boost::type_traits::ice_not<
boost::detail::is_char_or_wchar<no_cv_src>::value // single character widening is optimized
>::value // and does not requires stringbuffer
> is_string_widening_required_t;
typedef ::boost::type_traits::ice_or<
::boost::is_integral<no_cv_src>::value,
::boost::detail::is_this_float_conversion_optimized<no_cv_src, char_type >::value,
::boost::detail::is_char_or_wchar<src_char_type >::value
> is_source_input_optimized_t;
typedef boost::type_traits::ice_not< boost::type_traits::ice_or<
boost::is_integral<no_cv_src>::value,
boost::detail::is_this_float_conversion_optimized<no_cv_src, char_type >::value,
boost::detail::is_char_or_wchar<
BOOST_DEDUCED_TYPENAME deduce_src_char_metafunc::stage1_type // if we did not get character type at stage1
>::value // then we have no optimization for that type
>::value > is_source_input_not_optimized_t;
// Target type must be default constructible
Target result;
// If we have an optimized conversion for
// Source, we do not need to construct stringbuf.
const bool requires_stringbuf = ::boost::type_traits::ice_or<
is_string_widening_required_t::value,
::boost::type_traits::ice_not< is_source_input_optimized_t::value >::value
>::value;
BOOST_STATIC_CONSTANT(bool, requires_stringbuf =
(boost::type_traits::ice_or<
is_string_widening_required_t::value, is_source_input_not_optimized_t::value
>::value)
);
typedef detail::lexical_stream_limited_src<char_type, traits, requires_stringbuf > interpreter_type;
@@ -2163,7 +2267,7 @@ namespace boost {
typedef Source source_type ;
typedef BOOST_DEDUCED_TYPENAME mpl::if_<
::boost::is_arithmetic<Source>, Source, Source const&
boost::is_arithmetic<Source>, Source, Source const&
>::type argument_type ;
static source_type nearbyint ( argument_type s )
@@ -2247,19 +2351,19 @@ namespace boost {
{
static inline Target lexical_cast_impl(const Source &arg)
{
typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c<
::boost::type_traits::ice_and<
::boost::type_traits::ice_or<
::boost::is_signed<Source>::value,
::boost::is_float<Source>::value
typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
boost::type_traits::ice_and<
boost::type_traits::ice_or<
boost::is_signed<Source>::value,
boost::is_float<Source>::value
>::value,
::boost::type_traits::ice_not<
::boost::is_same<Source, bool>::value
boost::type_traits::ice_not<
boost::is_same<Source, bool>::value
>::value,
::boost::type_traits::ice_not<
::boost::is_same<Target, bool>::value
boost::type_traits::ice_not<
boost::is_same<Target, bool>::value
>::value,
::boost::is_unsigned<Target>::value
boost::is_unsigned<Target>::value
>::value,
lexical_cast_dynamic_num_ignoring_minus<Target, Source>,
lexical_cast_dynamic_num_not_ignoring_minus<Target, Source>
@@ -2273,86 +2377,44 @@ namespace boost {
template <typename Target, typename Source>
inline Target lexical_cast(const Source &arg)
{
typedef BOOST_DEDUCED_TYPENAME ::boost::detail::array_to_pointer_decay<Source>::type src;
typedef BOOST_DEDUCED_TYPENAME boost::detail::array_to_pointer_decay<Source>::type src;
typedef BOOST_DEDUCED_TYPENAME ::boost::type_traits::ice_or<
::boost::detail::is_xchar_to_xchar<Target, src >::value,
::boost::detail::is_char_array_to_stdstring<Target, src >::value,
::boost::type_traits::ice_and<
::boost::is_same<Target, src >::value,
::boost::detail::is_stdstring<Target >::value
typedef BOOST_DEDUCED_TYPENAME boost::type_traits::ice_or<
boost::detail::is_xchar_to_xchar<Target, src >::value,
boost::detail::is_char_array_to_stdstring<Target, src >::value,
boost::type_traits::ice_and<
boost::is_same<Target, src >::value,
boost::detail::is_stdstring<Target >::value
>::value
> shall_we_copy_t;
typedef BOOST_DEDUCED_TYPENAME
::boost::detail::is_arithmetic_and_not_xchars<Target, src > shall_we_copy_with_dynamic_check_t;
boost::detail::is_arithmetic_and_not_xchars<Target, src > shall_we_copy_with_dynamic_check_t;
typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c<
typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
shall_we_copy_t::value,
::boost::detail::lexical_cast_copy<src >,
BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c<
boost::detail::lexical_cast_copy<src >,
BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
shall_we_copy_with_dynamic_check_t::value,
::boost::detail::lexical_cast_dynamic_num<Target, src >,
::boost::detail::lexical_cast_do_cast<Target, src >
boost::detail::lexical_cast_dynamic_num<Target, src >,
boost::detail::lexical_cast_do_cast<Target, src >
>::type
>::type caster_type;
return caster_type::lexical_cast_impl(arg);
}
template <typename Target>
inline Target lexical_cast(const char* chars, std::size_t count)
template <typename Target, typename CharType>
inline Target lexical_cast(const CharType* chars, std::size_t count)
{
return ::boost::lexical_cast<Target>(
::boost::iterator_range<const char*>(chars, chars + count)
);
}
BOOST_STATIC_ASSERT_MSG(boost::detail::is_char_or_wchar<CharType>::value,
"CharType must be a character or wide character type");
template <typename Target>
inline Target lexical_cast(const unsigned char* chars, std::size_t count)
{
return ::boost::lexical_cast<Target>(
::boost::iterator_range<const unsigned char*>(chars, chars + count)
return boost::lexical_cast<Target>(
boost::iterator_range<const CharType*>(chars, chars + count)
);
}
template <typename Target>
inline Target lexical_cast(const signed char* chars, std::size_t count)
{
return ::boost::lexical_cast<Target>(
::boost::iterator_range<const signed char*>(chars, chars + count)
);
}
#ifndef BOOST_LCAST_NO_WCHAR_T
template <typename Target>
inline Target lexical_cast(const wchar_t* chars, std::size_t count)
{
return ::boost::lexical_cast<Target>(
::boost::iterator_range<const wchar_t*>(chars, chars + count)
);
}
#endif
#ifndef BOOST_NO_CHAR16_T
template <typename Target>
inline Target lexical_cast(const char16_t* chars, std::size_t count)
{
return ::boost::lexical_cast<Target>(
::boost::iterator_range<const char16_t*>(chars, chars + count)
);
}
#endif
#ifndef BOOST_NO_CHAR32_T
template <typename Target>
inline Target lexical_cast(const char32_t* chars, std::size_t count)
{
return ::boost::lexical_cast<Target>(
::boost::iterator_range<const char32_t*>(chars, chars + count)
);
}
#endif
} // namespace boost
#else // #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION

View File

@@ -49,5 +49,6 @@ test-suite conversion
[ run lexical_cast_iterator_range_test.cpp ]
[ run lexical_cast_arrays_test.cpp ]
[ run lexical_cast_integral_types_test.cpp ]
[ run lexical_cast_stream_detection_test.cpp ]
;

View File

@@ -0,0 +1,307 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2011-2012.
//
// 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).
#include <boost/config.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/lexical_cast.hpp>
#include <iostream>
///////////////////////// char streamable classes ///////////////////////////////////////////
struct streamable_easy { enum ENU {value = 0}; };
std::ostream& operator << (std::ostream& ostr, const streamable_easy&) {
return ostr << streamable_easy::value;
}
std::istream& operator >> (std::istream& istr, const streamable_easy&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, streamable_easy::value);
return istr;
}
struct streamable_medium { enum ENU {value = 1}; };
template <class CharT>
typename boost::enable_if<boost::is_same<CharT, char>, std::basic_ostream<CharT>&>::type
operator << (std::basic_ostream<CharT>& ostr, const streamable_medium&) {
return ostr << streamable_medium::value;
}
template <class CharT>
typename boost::enable_if<boost::is_same<CharT, char>, std::basic_istream<CharT>&>::type
operator >> (std::basic_istream<CharT>& istr, const streamable_medium&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, streamable_medium::value);
return istr;
}
struct streamable_hard { enum ENU {value = 2}; };
template <class CharT, class TraitsT>
typename boost::enable_if<boost::is_same<CharT, char>, std::basic_ostream<CharT, TraitsT>&>::type
operator << (std::basic_ostream<CharT, TraitsT>& ostr, const streamable_hard&) {
return ostr << streamable_hard::value;
}
template <class CharT, class TraitsT>
typename boost::enable_if<boost::is_same<CharT, char>, std::basic_istream<CharT, TraitsT>&>::type
operator >> (std::basic_istream<CharT, TraitsT>& istr, const streamable_hard&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, streamable_hard::value);
return istr;
}
struct streamable_hard2 { enum ENU {value = 3}; };
template <class TraitsT>
std::basic_ostream<char, TraitsT>& operator << (std::basic_ostream<char, TraitsT>& ostr, const streamable_hard2&) {
return ostr << streamable_hard2::value;
}
template <class TraitsT>
std::basic_istream<char, TraitsT>& operator >> (std::basic_istream<char, TraitsT>& istr, const streamable_hard2&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, streamable_hard2::value);
return istr;
}
///////////////////////// wchar_t streamable classes ///////////////////////////////////////////
struct wstreamable_easy { enum ENU {value = 4}; };
std::wostream& operator << (std::wostream& ostr, const wstreamable_easy&) {
return ostr << wstreamable_easy::value;
}
std::wistream& operator >> (std::wistream& istr, const wstreamable_easy&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, wstreamable_easy::value);
return istr;
}
struct wstreamable_medium { enum ENU {value = 5}; };
template <class CharT>
typename boost::enable_if<boost::is_same<CharT, wchar_t>, std::basic_ostream<CharT>& >::type
operator << (std::basic_ostream<CharT>& ostr, const wstreamable_medium&) {
return ostr << wstreamable_medium::value;
}
template <class CharT>
typename boost::enable_if<boost::is_same<CharT, wchar_t>, std::basic_istream<CharT>& >::type
operator >> (std::basic_istream<CharT>& istr, const wstreamable_medium&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, wstreamable_medium::value);
return istr;
}
struct wstreamable_hard { enum ENU {value = 6}; };
template <class CharT, class TraitsT>
typename boost::enable_if<boost::is_same<CharT, wchar_t>, std::basic_ostream<CharT, TraitsT>&>::type
operator << (std::basic_ostream<CharT, TraitsT>& ostr, const wstreamable_hard&) {
return ostr << wstreamable_hard::value;
}
template <class CharT, class TraitsT>
typename boost::enable_if<boost::is_same<CharT, wchar_t>, std::basic_istream<CharT, TraitsT>&>::type
operator >> (std::basic_istream<CharT, TraitsT>& istr, const wstreamable_hard&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, wstreamable_hard::value);
return istr;
}
struct wstreamable_hard2 { enum ENU {value = 7}; };
template <class TraitsT>
std::basic_ostream<wchar_t, TraitsT>& operator << (std::basic_ostream<wchar_t, TraitsT>& ostr, const wstreamable_hard2&) {
return ostr << wstreamable_hard2::value;
}
template <class TraitsT>
std::basic_istream<wchar_t, TraitsT>& operator >> (std::basic_istream<wchar_t, TraitsT>& istr, const wstreamable_hard2&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, wstreamable_hard2::value);
return istr;
}
///////////////////////// char and wchar_t streamable classes ///////////////////////////////////////////
struct bistreamable_easy { enum ENU {value = 8}; };
std::ostream& operator << (std::ostream& ostr, const bistreamable_easy&) {
return ostr << bistreamable_easy::value;
}
std::istream& operator >> (std::istream& istr, const bistreamable_easy&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_easy::value);
return istr;
}
std::wostream& operator << (std::wostream& ostr, const bistreamable_easy&) {
return ostr << bistreamable_easy::value + 100;
}
std::wistream& operator >> (std::wistream& istr, const bistreamable_easy&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_easy::value + 100);
return istr;
}
struct bistreamable_medium { enum ENU {value = 9}; };
template <class CharT>
std::basic_ostream<CharT>& operator << (std::basic_ostream<CharT>& ostr, const bistreamable_medium&) {
return ostr << bistreamable_medium::value + (sizeof(CharT) == 1 ? 0 : 100);
}
template <class CharT>
std::basic_istream<CharT>& operator >> (std::basic_istream<CharT>& istr, const bistreamable_medium&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_medium::value + (sizeof(CharT) == 1 ? 0 : 100));
return istr;
}
struct bistreamable_hard { enum ENU {value = 10}; };
template <class CharT, class TraitsT>
std::basic_ostream<CharT, TraitsT>& operator << (std::basic_ostream<CharT, TraitsT>& ostr, const bistreamable_hard&) {
return ostr << bistreamable_hard::value + (sizeof(CharT) == 1 ? 0 : 100);
}
template <class CharT, class TraitsT>
std::basic_istream<CharT, TraitsT>& operator >> (std::basic_istream<CharT, TraitsT>& istr, const bistreamable_hard&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_hard::value + (sizeof(CharT) == 1 ? 0 : 100));
return istr;
}
struct bistreamable_hard2 { enum ENU {value = 11}; };
template <class TraitsT>
std::basic_ostream<char, TraitsT>& operator << (std::basic_ostream<char, TraitsT>& ostr, const bistreamable_hard2&) {
return ostr << bistreamable_hard2::value;
}
template <class TraitsT>
std::basic_istream<char, TraitsT>& operator >> (std::basic_istream<char, TraitsT>& istr, const bistreamable_hard2&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_hard2::value);
return istr;
}
template <class TraitsT>
std::basic_ostream<wchar_t, TraitsT>& operator << (std::basic_ostream<wchar_t, TraitsT>& ostr, const bistreamable_hard2&) {
return ostr << bistreamable_hard2::value + 100;
}
template <class TraitsT>
std::basic_istream<wchar_t, TraitsT>& operator >> (std::basic_istream<wchar_t, TraitsT>& istr, const bistreamable_hard2&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_hard2::value + 100);
return istr;
}
void test_ostream_character_detection();
void test_istream_character_detection();
void test_mixed_stream_character_detection();
boost::unit_test::test_suite *init_unit_test_suite(int, char *[])
{
boost::unit_test::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast stream character detection");
suite->add(BOOST_TEST_CASE(&test_ostream_character_detection));
suite->add(BOOST_TEST_CASE(&test_istream_character_detection));
suite->add(BOOST_TEST_CASE(&test_mixed_stream_character_detection));
return suite;
}
template <class T>
static void test_ostr_impl() {
T streamable;
BOOST_CHECK_EQUAL(T::value, boost::lexical_cast<int>(streamable));
BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(T::value), boost::lexical_cast<std::string>(streamable));
}
template <class T>
static void test_wostr_impl() {
T streamable;
BOOST_CHECK_EQUAL(T::value, boost::lexical_cast<int>(streamable));
// BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(T::value), boost::lexical_cast<std::string>(streamable)); // Shall not compile???
BOOST_CHECK(boost::lexical_cast<std::wstring>(T::value) == boost::lexical_cast<std::wstring>(streamable));
}
template <class T>
static void test_bistr_impl() {
T streamable;
BOOST_CHECK_EQUAL(T::value, boost::lexical_cast<int>(streamable));
BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(T::value), boost::lexical_cast<std::string>(streamable));
BOOST_CHECK(boost::lexical_cast<std::wstring>(T::value + 100) == boost::lexical_cast<std::wstring>(streamable));
}
void test_ostream_character_detection() {
test_ostr_impl<streamable_easy>();
test_ostr_impl<streamable_medium>();
test_ostr_impl<streamable_hard>();
test_ostr_impl<streamable_hard2>();
test_wostr_impl<wstreamable_easy>();
test_wostr_impl<wstreamable_medium>();
test_wostr_impl<wstreamable_hard>();
test_wostr_impl<wstreamable_hard2>();
test_bistr_impl<bistreamable_easy>();
test_bistr_impl<bistreamable_medium>();
test_bistr_impl<bistreamable_hard>();
test_bistr_impl<bistreamable_hard2>();
}
template <class T>
static void test_istr_impl() {
boost::lexical_cast<T>(T::value);
boost::lexical_cast<T>(boost::lexical_cast<std::string>(T::value));
}
template <class T>
static void test_wistr_impl() {
boost::lexical_cast<T>(T::value);
//boost::lexical_cast<T>(boost::lexical_cast<std::string>(T::value)); // Shall not compile???
boost::lexical_cast<T>(boost::lexical_cast<std::wstring>(T::value));
}
template <class T>
static void test_bistr_instr_impl() {
boost::lexical_cast<T>(T::value);
boost::lexical_cast<T>(boost::lexical_cast<std::string>(T::value));
boost::lexical_cast<T>(boost::lexical_cast<std::wstring>(T::value + 100));
}
void test_istream_character_detection() {
test_istr_impl<streamable_easy>();
test_istr_impl<streamable_medium>();
test_istr_impl<streamable_hard>();
test_istr_impl<streamable_hard2>();
test_wistr_impl<wstreamable_easy>();
test_wistr_impl<wstreamable_medium>();
test_wistr_impl<wstreamable_hard>();
test_wistr_impl<wstreamable_hard2>();
test_bistr_instr_impl<bistreamable_easy>();
test_bistr_instr_impl<bistreamable_medium>();
test_bistr_instr_impl<bistreamable_hard>();
test_bistr_instr_impl<bistreamable_hard2>();
}
struct wistreamble_ostreamable { enum ENU {value = 200}; };
std::ostream& operator << (std::ostream& ostr, const wistreamble_ostreamable&) {
return ostr << wistreamble_ostreamable::value;
}
std::wistream& operator >> (std::wistream& istr, const wistreamble_ostreamable&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, wistreamble_ostreamable::value);
return istr;
}
struct istreamble_wostreamable { enum ENU {value = 201}; };
std::wostream& operator << (std::wostream& ostr, const istreamble_wostreamable&) {
return ostr << istreamble_wostreamable::value;
}
std::istream& operator >> (std::istream& istr, const istreamble_wostreamable&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, istreamble_wostreamable::value);
return istr;
}
void test_mixed_stream_character_detection() {
//boost::lexical_cast<std::wstring>(std::string("qwe")); // TODO: ALLOW IT AS EXTENSION!
boost::lexical_cast<wistreamble_ostreamable>(wistreamble_ostreamable::value);
BOOST_CHECK_EQUAL(boost::lexical_cast<int>(wistreamble_ostreamable()), wistreamble_ostreamable::value);
boost::lexical_cast<istreamble_wostreamable>(istreamble_wostreamable::value);
BOOST_CHECK_EQUAL(boost::lexical_cast<int>(istreamble_wostreamable()), istreamble_wostreamable::value);
}