Library: allow for pretty-printing of smart-ptr values

- an extension to our custom toString and typeString helpers.
- currently just for shared_ptr and unique_ptr
- might add further overloads for other smart-ptr types
This commit is contained in:
Fischlurch 2016-07-30 23:19:21 +02:00
parent 52918b069f
commit cbe29fead3
4 changed files with 71 additions and 0 deletions

View file

@ -214,6 +214,9 @@ apologies for that."
static regex mapAllocator {"(map<(" TYP_EXP "), (" TYP_EXP ")),.+allocator<pair<\\2 const, \\3>\\s*>\\s*"
, regex::ECMAScript | regex::optimize};
static regex uniquePtr {"unique_ptr<(\\w+), default_delete<\\1>\\s*"
, regex::ECMAScript | regex::optimize};
static regex lumieraP {"P<(\\w+), shared_ptr<\\1>\\s*"
, regex::ECMAScript | regex::optimize};
@ -224,6 +227,7 @@ apologies for that."
end = regex_replace(pos, pos, end, commonPrefixes, "");
end = regex_replace(pos, pos, end, stdAllocator, "$1");
end = regex_replace(pos, pos, end, mapAllocator, "$1");
end = regex_replace(pos, pos, end, uniquePtr, "unique_ptr<$1");
end = regex_replace(pos, pos, end, lumieraP, "P<$1");
typeName.resize(end - typeName.begin());

View file

@ -95,6 +95,9 @@ namespace util {
/** toggle to prefer specialisation with direct lexical conversion */
template<typename X>
using enable_LexicalConversion = lib::meta::enable_if< lib::meta::use_LexicalConversion<X>>;
template<typename SP>
using show_SmartPointer = lib::meta::enable_if< lib::meta::is_smart_ptr<typename lib::meta::Strip<SP>::TypeReferred>>;
}
@ -111,6 +114,15 @@ namespace util {
catch(...) { return FAILURE_INDICATOR; }
};
template<typename SP>
struct StringConv<SP, show_SmartPointer<SP>>
{
static std::string
invoke (SP const& smP) noexcept
try { return showSmartPtr (smP, lib::meta::typeSymbol(smP)); }
catch(...) { return FAILURE_INDICATOR; }
};
/** explicit specialisation to control precision of double values.
* @note we set an explicit precision, since this is a diagnostic facility
* and we typically do not want to see all digits, but, for test code,

View file

@ -278,6 +278,33 @@ namespace util {
};
};
template<typename SP>
struct _is_smart_wrapper
: std::false_type
{ };
template<typename T>
struct _is_smart_wrapper<std::shared_ptr<T>>
: std::true_type
{ };
template <typename T, typename D>
struct _is_smart_wrapper<std::unique_ptr<T,D>>
: std::true_type
{ };
template<typename SP>
struct _shall_show_smartWrapper
{
enum{ value = not _shall_convert_toString<SP>::value
and _is_smart_wrapper<typename std::remove_reference<
typename std::remove_cv<SP>::type>::type>::value
};
};
inline void
_clear_errorflag()
@ -404,6 +431,24 @@ namespace util {
}
};
template<typename SP>
struct _Fmt::Converter<SP, lib::meta::enable_if<_shall_show_smartWrapper<SP>> >
{
static void
dump (SP const& smP, Implementation& impl)
try {
format (showSmartPtr (smP, lib::meta::typeSymbol(smP)), impl);
}
catch(std::exception const& ex)
{
format (_log_and_stringify(ex), impl);
}
catch(...)
{
format (_log_unknown_exception(), impl);
}
};
/** some basic types are directly forwarded down to the implementation;
* @note this requires explicit specialisations in format-string.cpp */
template<typename VAL>

View file

@ -374,6 +374,16 @@ namespace util {
: BOTTOM_INDICATOR + " «" + typeStr(ptr) + "»";
}
template<typename SP>
inline std::string
showSmartPtr (SP const& smPtr, std::string label = "smP")
{
using TargetType = typename SP::element_type;
return smPtr? label+"("+showAddr(smPtr.get()) + ") ↗" + StringConv<TargetType>::invoke(*smPtr)
: BOTTOM_INDICATOR + " «" + typeStr(smPtr) + "»";
}
/** human readable display of boolean values
* @return "`true`" or "`false`"
*/