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:
Fischlurch 2016-01-06 04:36:53 +01:00
parent 60a7e7acb2
commit ee52a83cb2
2 changed files with 108 additions and 31 deletions

View file

@ -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
View 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*/