fix a problem with formatting arbitrary types; reneable the broken tests

This commit is contained in:
Fischlurch 2009-08-28 20:33:20 +02:00
parent 151d17e4de
commit 1533e5bd0d
5 changed files with 72 additions and 5 deletions

View file

@ -39,6 +39,7 @@
#include <string>
#include <cstring>
#include <typeinfo>
#include <boost/lexical_cast.hpp>
#include <boost/utility/enable_if.hpp>
@ -46,6 +47,7 @@
namespace util {
using lumiera::typelist::can_ToString;
using lumiera::typelist::can_lexical2string;
using lumiera::Symbol;
using boost::enable_if;
using boost::disable_if;
@ -70,11 +72,36 @@ namespace util {
{
return "";
}
template<typename X>
inline string
invoke_indirect2string ( typename enable_if< can_lexical2string<X>,
X >::type const& val)
{
try { return boost::lexical_cast<string> (val); }
catch(...) { return ""; }
}
template<typename X>
inline string
invoke_indirect2string ( typename disable_if< can_lexical2string<X>,
X >::type const&)
{
return "";
}
}
/** try to get an object converted to string */
/** try to get an object converted to string.
* An custom/standard conversion to string is used,
* if applicable; otherwise, some standard types can be
* converted by a lexical_cast (based on operator<< ).
* Otherwise, either the fallback string is used, or just
* a string denoting the (mangled) type.
*/
template<typename TY>
inline string
str ( TY const& val
@ -86,8 +113,17 @@ namespace util {
return string(prefix) + invoke_2string<TY>(val);
else
return fallback? fallback
: tyStr(val);
{
if (can_lexical2string<TY>::value)
{
string res (invoke_indirect2string<TY> (val));
if ("" != res)
return string(prefix) + res;
}
return fallback? fallback
: tyStr(val);
}
}

View file

@ -28,11 +28,17 @@
#include "lib/meta/util.hpp"
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
#include <boost/utility/enable_if.hpp>
#include <string>
namespace lumiera {
namespace typelist {
using boost::enable_if;
using boost::is_arithmetic;
/** Trait template for detecting if a type can be converted to string.
* For example, this allows to write specialisations with the help of
@ -46,6 +52,24 @@ namespace typelist {
};
/** Trait template for guarding \c lexical_cast<..> expressions.
* Such an expression won't even compile for some types, because of
* missing or ambiguous output operator(s).
* Ideally, there would be some automatic detection (relying on the
* existence of an operator<< for the given type. But I couldn't make
* this work, so I fell back on just declaring types which are known
* to work with lexical_cast to string
* @note this compile-time trait can't predict if such an conversion
* to string will be successful at runtime; indeed it may throw,
* so you should additionally guard the invocation with try-catch!
*/
template<typename X>
struct can_lexical2string
{
enum { value = is_arithmetic<X>::value
};
};
}} // namespace lumiera::typelist
#endif

View file

@ -240,6 +240,9 @@ out: «..util.test.Reticent.»
out: <no comment>
out: ^hey Joe!
out: ^he says: hey Joe!
out: ^the truth: 0
out: ^just a number: 1.234e\+56
out: ^12345X
return: 0
END

View file

@ -7,7 +7,7 @@ PLANNED "CommandBasic_test" CommandBasic_test <<END
END
PLANNED "Argument & Memento handling" CommandArgument_test <<END
TEST "Argument & Memento handling" CommandArgument_test <<END
out: Command-State. arguments=unbound, ·noUNDO·.
out: capture state...
out: Command-State. arguments=Closure\(\), ·noUNDO·.
@ -35,7 +35,7 @@ out: RESET...undoIt\(time=00:..:....00\)----memento-:START...doIt\( Time=00:..:.
END
PLANNED "Command functor and UNDO functor" CommandMutation_test <<END
TEST "Command functor and UNDO functor" CommandMutation_test <<END
out: Mutation\(untied\)
out: param values: Closure\(23\)
out: Mutation\(Closure\(23\)\)

View file

@ -75,6 +75,10 @@ namespace test {
cout << str (chatterer) << endl;
cout << str (chatterer, "he says: ", "<no comment>") << endl;
cout << str (false, "the truth: ") << endl;
cout << str (12.34e55, "just a number: ") << endl;
cout << str (short(12)) << str (345L) << str ('X') << endl;
}