stream-output(#985): use custom string conversions
provide a generic overload for the stream inserter operator<< to use custom string conversions when applicable. The overload will be disabled when a direct lexical conversion is possible (which means, we can expect the output stream to know allready how to print those values, like e.g. all kinds of numbers). Additionally, we provide a pretty-printing mechansim for pointers, to show the address and possibly invoke a custom string conversion on the pointee
This commit is contained in:
parent
60a7e7acb2
commit
ee52a83cb2
2 changed files with 108 additions and 31 deletions
|
|
@ -72,6 +72,7 @@ typedef unsigned int uint;
|
|||
|
||||
#include "lib/meta/util.hpp"
|
||||
#include "lib/meta/trait.hpp"
|
||||
#include "lib/format-cout.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <type_traits>
|
||||
|
|
@ -85,6 +86,7 @@ using lib::meta::typeStr;
|
|||
using lib::meta::is_basically;
|
||||
using lib::meta::can_lexical2string;
|
||||
using lib::meta::can_convertToString;
|
||||
using lib::meta::use_StringConversion4Stream;
|
||||
using lib::meta::CustomStringConv;
|
||||
using lib::meta::Strip;
|
||||
|
||||
|
|
@ -112,35 +114,7 @@ stringz (P<X> ptr)
|
|||
}
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////planned new ostream inclusion
|
||||
namespace {
|
||||
|
||||
template<typename X>
|
||||
struct use_StringConversion4Stream
|
||||
: __and_< std::is_class<typename Strip<X>::TypePlain>
|
||||
,__not_<std::is_pointer<X>>
|
||||
,__not_<can_lexical2string<X>>
|
||||
>
|
||||
{ };
|
||||
}
|
||||
|
||||
template<typename X, typename = enable_if <use_StringConversion4Stream<X>>>
|
||||
std::ostream&
|
||||
operator<< (std::ostream& os, X const& obj)
|
||||
{
|
||||
return os << CustomStringConv<X>::invoke (obj);
|
||||
}
|
||||
|
||||
template<typename X, typename = enable_if <use_StringConversion4Stream<X>>>
|
||||
std::ostream&
|
||||
operator<< (std::ostream& os, X* ptr)
|
||||
{
|
||||
if (ptr)
|
||||
return os << (void*)ptr << " ↗" << *ptr;
|
||||
else
|
||||
return os << "⟂ «" << typeStr<X>() << "»";
|
||||
}
|
||||
namespace std {
|
||||
|
||||
template<typename X>
|
||||
std::ostream&
|
||||
|
|
@ -148,8 +122,7 @@ stringz (P<X> ptr)
|
|||
{
|
||||
return os << stringz (ptr);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////planned new ostream inclusion
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
104
src/lib/format-cout.hpp
Normal file
104
src/lib/format-cout.hpp
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
FORMAT-COUT.hpp - use custom string conversions in stream output
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2016, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/** @file format-cout.hpp
|
||||
** Automatically use custom string conversion in C++ stream output.
|
||||
** This diagnostics facility allows just to dump any object into `cout` or `cerr`.
|
||||
** Pointers will be detected, checked for NULL and printed as address, followed
|
||||
** by the representation of the pointee. When the displayed entity defines an
|
||||
** `operator string()`, this custom string conversion will be used (suppressing
|
||||
** any exceptions, of course). As fallback, a simplified type string is printed.
|
||||
**
|
||||
** @see FormatHelper_test
|
||||
** @see [frontend for boost::format, printf-style](format-string.hpp)
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LIB_FORMAT_COUT_H
|
||||
#define LIB_FORMAT_COUT_H
|
||||
|
||||
#include "lib/format-obj.hpp"
|
||||
//#include "lib/util.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
// make those generally visible
|
||||
using std::cout;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
|
||||
|
||||
|
||||
namespace lib {
|
||||
namespace meta {
|
||||
|
||||
/** when to use custom string conversions for output streams */
|
||||
template<typename X>
|
||||
struct use_StringConversion4Stream
|
||||
: __and_<std::is_class<typename Strip<X>::TypePlain>
|
||||
,__not_<std::is_pointer<X>>
|
||||
,__not_<can_lexical2string<X>>
|
||||
>
|
||||
{ };
|
||||
}}
|
||||
|
||||
|
||||
|
||||
namespace std {
|
||||
|
||||
namespace { // toggle for the following generic overloads of operator<<
|
||||
|
||||
template<typename X>
|
||||
using enable_StringConversion = lib::meta::enable_if< lib::meta::use_StringConversion4Stream<X>>;
|
||||
}
|
||||
|
||||
|
||||
/** generic overload to use custom string conversions in output */
|
||||
template<typename X, typename = enable_StringConversion<X>>
|
||||
ostream&
|
||||
operator<< (ostream& os, X const& obj)
|
||||
{
|
||||
return os << lib::meta::CustomStringConv<X>::invoke (obj);
|
||||
}
|
||||
|
||||
|
||||
/** generic overload to pretty-print any pointer in output
|
||||
* @note possibly also invokes custom string conversion,
|
||||
* in case the pointee defines one
|
||||
*/
|
||||
template<typename X, typename = enable_StringConversion<X>>
|
||||
ostream&
|
||||
operator<< (ostream& os, X* ptr)
|
||||
{
|
||||
if (ptr)
|
||||
return os << (void*)ptr << " ↗" << *ptr;
|
||||
else
|
||||
return os << "⟂ «" << lib::meta::typeStr<X>() << "»";
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace std
|
||||
#endif /*LIB_FORMAT_COUT_H*/
|
||||
Loading…
Reference in a new issue