// with additional fixes and suggestions from Gennaro Prota,
// Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov,
// and other Boosters
-// when: November 2000, March 2003
+// when: November 2000, March 2003, June 2005
+#include <cstddef>
#include <string>
#include <typeinfo>
#include <boost/config.hpp>
#include <boost/limits.hpp>
+#include <boost/throw_exception.hpp>
#include <boost/type_traits/is_pointer.hpp>
#ifdef BOOST_NO_STRINGSTREAM
#if defined(BOOST_NO_STRINGSTREAM) || \
defined(BOOST_NO_STD_WSTRING) || \
- defined(BOOST_NO_STD_LOCALE) || \
- defined(BOOST_NO_CWCHAR) || \
- defined(BOOST_MSVC) && (BOOST_MSVC <= 1200)
+ defined(BOOST_NO_STD_LOCALE)
#define DISABLE_WIDE_CHAR_SUPPORT
#endif
-#ifdef BOOST_NO_INTRINSIC_WCHAR_T
-#include <cwchar>
-#endif
-
namespace boost
{
// exception used to indicate runtime lexical_cast failure
class bad_lexical_cast : public std::bad_cast
{
public:
+ bad_lexical_cast() :
+ source(&typeid(void)), target(&typeid(void))
+ {
+ }
+ bad_lexical_cast(
+ const std::type_info &source_type,
+ const std::type_info &target_type) :
+ source(&source_type), target(&target_type)
+ {
+ }
+ const std::type_info &source_type() const
+ {
+ return *source;
+ }
+ const std::type_info &target_type() const
+ {
+ return *target;
+ }
+ virtual const char *what() const throw()
+ {
+ return "bad lexical cast: "
+ "source type value could not be interpreted as target";
+ }
virtual ~bad_lexical_cast() throw()
{
}
+ private:
+ const std::type_info *source;
+ const std::type_info *target;
};
- namespace detail // actual underlying concrete exception type
- {
- template<typename Target, typename Source>
- class no_lexical_conversion : public bad_lexical_cast
- {
- public:
- no_lexical_conversion()
- : description(
- std::string() + "bad lexical cast: " +
- "source type value could not be interpreted as target, Target=" +
- typeid(Target).name() + ", Source=" + typeid(Source).name())
- {
- }
- virtual ~no_lexical_conversion() throw()
- {
- }
- virtual const char *what() const throw()
- {
- return description.c_str();
- }
- private:
- const std::string description; // static initialization fails on MSVC6
- };
- }
-
namespace detail // selectors for choosing stream character type
{
template<typename Type>
};
#ifndef DISABLE_WIDE_CHAR_SUPPORT
+#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
template<>
struct stream_char<wchar_t>
{
typedef wchar_t type;
};
+#endif
template<>
struct stream_char<wchar_t *>
template<typename Target, typename Source>
class lexical_stream
{
+ private:
+ typedef typename widest_char<
+ typename stream_char<Target>::type,
+ typename stream_char<Source>::type>::type char_type;
+
public:
lexical_stream()
{
}
bool operator<<(const Source &input)
{
- return stream << input;
+ return !(stream << input).fail();
}
template<typename InputStreamable>
bool operator>>(InputStreamable &output)
{
return !is_pointer<InputStreamable>::value &&
stream >> output &&
- (stream >> std::ws).eof();
+ stream.get() ==
+#if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
+// GCC 2.9x lacks std::char_traits<>::eof().
+// We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
+// configurations, which do provide std::char_traits<>::eof().
+
+ EOF;
+#else
+ std::char_traits<char_type>::eof();
+#endif
}
bool operator>>(std::string &output)
{
}
#endif
private:
- typedef typename widest_char<
- typename stream_char<Target>::type,
- typename stream_char<Source>::type>::type char_type;
-
#if defined(BOOST_NO_STRINGSTREAM)
std::strstream stream;
#elif defined(BOOST_NO_STD_LOCALE)
};
}
+ #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+
+ // call-by-const reference version
+
+ namespace detail
+ {
+ template<class T>
+ struct array_to_pointer_decay
+ {
+ typedef T type;
+ };
+
+ template<class T, std::size_t N>
+ struct array_to_pointer_decay<T[N]>
+ {
+ typedef const T * type;
+ };
+ }
+
+ template<typename Target, typename Source>
+ Target lexical_cast(const Source &arg)
+ {
+ typedef typename detail::array_to_pointer_decay<Source>::type NewSource;
+
+ detail::lexical_stream<Target, NewSource> interpreter;
+ Target result;
+
+ if(!(interpreter << arg && interpreter >> result))
+ throw_exception(bad_lexical_cast(typeid(NewSource), typeid(Target)));
+ return result;
+ }
+
+ #else
+
+ // call-by-value fallback version (deprecated)
+
template<typename Target, typename Source>
Target lexical_cast(Source arg)
{
Target result;
if(!(interpreter << arg && interpreter >> result))
- throw detail::no_lexical_conversion<Target, Source>();
+ throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)));
return result;
}
+
+ #endif
}
-// Copyright Kevlin Henney, 2000-2003. All rights reserved.
-//
-// Permission to use, copy, modify, and distribute this software for any
-// purpose is hereby granted without fee, provided that this copyright and
-// permissions notice appear in all copies and derivatives.
+// Copyright Kevlin Henney, 2000-2005. All rights reserved.
//
-// This software is provided "as is" without express or implied warranty.
+// 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)
#undef DISABLE_WIDE_CHAR_SUPPORT
#endif