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

Reply via email to