Author: mordante
Date: Sat May 16 20:01:38 2009
New Revision: 35664
URL: http://svn.gna.org/viewcvs/wesnoth?rev=35664&view=rev
Log:
Rewrote the lexical_cast code.
When using boost::enable_if the code looks simpler.
Modified:
trunk/src/lexical_cast.hpp
trunk/src/tests/test_lexical_cast.cpp
Modified: trunk/src/lexical_cast.hpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/lexical_cast.hpp?rev=35664&r1=35663&r2=35664&view=diff
==============================================================================
--- trunk/src/lexical_cast.hpp (original)
+++ trunk/src/lexical_cast.hpp Sat May 16 20:01:38 2009
@@ -28,35 +28,25 @@
#ifndef LEXICAL_CAST_HPP_INCLUDED
#define LEXICAL_CAST_HPP_INCLUDED
-
#ifdef LEXICAL_CAST_DEBUG
-#undef SIGNATURE_2
-
+#undef DEBUG_THROW
/**
- * Signature for a function with two parameters.
+ * Throws an exception for debugging.
*
- * This version throws an exception with the typeid of the function used.
- *
- * @param res The result type.
- * @param name The name of the function.
- * @param p1 Parameter 1, both type and variable name.
- * @param p2 Parameter 2, both type and variable name.
+ * @param id The unique name to identify the function.
+ * @note this name is a user defined string and
+ * should not be modified once used!
*/
-#define SIGNATURE_2(res, name, p1, p2) res name(p1, p2) {
\
- static const std::type_info& type =
\
- typeid((res (tclass::*)(p1, p2)) &tclass::name);
\
- throw(&type);
-
+#define DEBUG_THROW(id) throw id;
#else
#include <string>
#include <sstream>
-#include <typeinfo>
+#include <boost/utility/enable_if.hpp>
#include <boost/type_traits.hpp>
-#define SIGNATURE_2(res, name, p1, p2) res name(p1, p2) {
-
+#define DEBUG_THROW(id)
#endif
/**
@@ -66,8 +56,13 @@
*/
namespace implementation {
-template<typename To, typename From>
-struct tlexical_cast;
+ template<
+ typename To
+ , typename From
+ , typename ToEnable = void
+ , typename FromEnable = void
+ >
+ struct tlexical_cast;
} // namespace implementation
@@ -92,84 +87,62 @@
namespace implementation {
-/** Fallback if no specialized cast exists. */
-template<typename To, typename From>
-To lexical_cast_generic(From value)
-{
- To result;
- std::stringstream sstr;
-
- if(!(sstr << value && sstr >> result)) {
- throw bad_lexical_cast();
- } else {
- return result;
- }
-}
-
/**
- * Base class for the conversion.
+ * Base class for the conversion.
*
* Since functions can't be partially specialized we use a class, which can be
* partially specialized for the conversion.
*
* @tparam To The type to convert to.
* @tparam From The type to convert from.
+ * @tparam ToEnable Filter to enable the To type.
+ * @tparam FromEnable Filter to enable the From type.
*/
-template<typename To, typename From>
+template<
+ typename To
+ , typename From
+ , typename ToEnable
+ , typename FromEnable
+>
struct tlexical_cast
{
- /**
- * The conversion operator.
- *
- * All (partially) specialized classes need to implement this function
to
- * do the conversion.
- *
- * @tparam To The type to convert to.
- * @tparam From The type to convert from.
- *
- * @param value The value to convert.
- *
- * @returns The converted value.
- */
To operator()(From value)
{
- return lexical_cast_generic<To/*,
- typename boost::add_reference<
- typename
boost::add_const<From>::type>::type*/>(value);
+ DEBUG_THROW("generic");
+
+ To result;
+ std::stringstream sstr;
+
+ if(!(sstr << value && sstr >> result)) {
+ throw bad_lexical_cast();
+ } else {
+ return result;
+ }
}
};
-/*
-template<typename To, typename From>
-struct tlexical_cast<To, From*>
+
+/**
+ * Specialized conversion class.
+ *
+ * Specialized for returning strings from an integral type or a pointer to an
+ * intergral type.
+ */
+template <typename From>
+struct tlexical_cast<
+ std::string
+ , From
+ , void
+ , typename boost::enable_if<boost::is_integral<
+ typename boost::remove_pointer<From>::type> >::type
+>
{
- To operator()(From* value)
+ std::string operator()(From value)
{
- return lexical_cast_generic<To, const From*>(value);
- }
-};
-*/
+ DEBUG_THROW("specialized - To std::string - From integral
(pointer)");
-/** Specialized class to return strings. */
-template<typename From>
-struct tlexical_cast<std::string, From>
-{
- typedef tlexical_cast<std::string, From> tclass;
-
- SIGNATURE_2(std::string, cast, From value, const boost::true_type&)
std::stringstream sstr;
sstr << value;
return sstr.str();
- }
-
- SIGNATURE_2(std::string, cast, From value, const boost::false_type&)
-
- return lexical_cast_generic<std::string, From>(value);
- }
-
- std::string operator()(From value)
- {
- return this->cast(value, boost::is_integral<
- typename boost::remove_pointer<From>::type>());
}
};
Modified: trunk/src/tests/test_lexical_cast.cpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/tests/test_lexical_cast.cpp?rev=35664&r1=35663&r2=35664&view=diff
==============================================================================
--- trunk/src/tests/test_lexical_cast.cpp (original)
+++ trunk/src/tests/test_lexical_cast.cpp Sat May 16 20:01:38 2009
@@ -23,36 +23,10 @@
#include "lexical_cast.hpp"
-
-
-
-
namespace test_throw {
#define LEXICAL_CAST_DEBUG
#include "lexical_cast.hpp"
-
-template<class TU, class TS, bool match> boost::test_tools::predicate_result
-exception_matches(const std::type_info* type)
-{
- typedef implementation::tlexical_cast<std::string, TU> tclass;
- static const std::type_info& expected_type =
- typeid((std::string (tclass::*) (TU, const boost::true_type&))
&tclass::cast);
- boost::test_tools::predicate_result res((*type == expected_type) ==
match);
- if(!res)
- res.message() << "Wrong type_info. Expected: " << (match ?
"equal" : "not equal") << '\n'
- << "type: " << typeid(TS).name() << '\n'
- << "caught: " << type->name() << '\n'
- << "expected: " << expected_type.name() << '\n';
- return res;
-}
-
-#define TEST_CASE(type_send, type_used, initializer)
\
- {
\
- type_send val = initializer value;
\
-
\
- BOOST_CHECK_EXCEPTION(lexical_cast<std::string>(val), const
std::type_info*, (exception_matches<type_used, type_send, match::value>)); \
- }
typedef boost::mpl::vector<
/* note Wesnoth's coding style doesn't allow w_char so ignore them. */
@@ -78,22 +52,48 @@
boost::mpl::back_inserter<test_match_types>
>::type test_types;
+
+namespace {
+
+ std::string result;
+
+bool validate(const char* str)
+{
+ return str == result;
+}
+
+} // namespace
+
+#define TEST_CASE(type_send, initializer) \
+ { \
+ type_send val = initializer value; \
+ \
+ BOOST_CHECK_EXCEPTION( \
+ lexical_cast<std::string>(val), const char*, validate);
\
+ }
+
BOOST_AUTO_TEST_CASE_TEMPLATE(test_lexical_cast_throw, T, test_types)
{
T value = T();
- typedef boost::mpl::contains<test_match_types, T> match;
- TEST_CASE(T, T, );
- TEST_CASE(const T, T, );
+ typedef typename boost::mpl::contains<test_match_types, T>::type test;
+ typedef typename boost::mpl::contains<test_match_types, int >::type
match;
- TEST_CASE(T&, T, );
- TEST_CASE(const T&, T, );
+ result = typeid(test) == typeid(match)
+ ? "specialized - To std::string - From integral
(pointer)"
+ : "generic";
- TEST_CASE(T*, T*, &);
- TEST_CASE(const T*, const T*, &);
+ TEST_CASE(T, );
+ TEST_CASE(const T, );
- TEST_CASE(T* const, T*, &);
- TEST_CASE(const T* const, const T*, &);
+ TEST_CASE(T&, );
+ TEST_CASE(const T&, );
+
+ TEST_CASE(T*, &);
+ TEST_CASE(const T*, &);
+
+ TEST_CASE(T* const, &);
+ TEST_CASE(const T* const, &);
}
#undef TEST_CASE
_______________________________________________
Wesnoth-commits mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-commits