basically a working solution for toString in ostream

...and learned a lot about the new type_traits on the way.

As it seems, it is not possible to get a clean error message
when passing an "object" with no custom string conversion;
instead, some overload for an rvalue-ostream kicks in.

probably I'll go for shoing a type string in these cases
This commit is contained in:
Fischlurch 2016-01-04 22:21:09 +01:00
parent 9f8ab48c51
commit d09a5846d4
7 changed files with 101 additions and 8 deletions

View file

@ -45,9 +45,11 @@ typedef unsigned int uint;
//#include "lib/util.hpp"
#include "lib/meta/util.hpp"
#include "lib/meta/trait.hpp"
#include <iostream>
//#include <cstdarg>
#include <type_traits>
#include <utility>
#include <string>
//#include <typeinfo>
@ -136,14 +138,102 @@ stringz (P<X> ptr)
}
/////////////////////////////////////////reworked traits
namespace {
using lib::meta::Strip;
using std::__or_;
using std::__and_;
using std::__not_;
template<typename T, typename U>
struct is_basically
: std::is_same <typename Strip<T>::TypePlain
,typename Strip<U>::TypePlain>
{ };
template<typename X>
struct can_lexical2string
: __or_< std::is_arithmetic<X>
, is_basically<X, string>
, is_basically<typename std::remove_all_extents<X>::type, char>
>
{ };
}
/////////////////////////////////////////reworked traits
/////////////////////////////////////////planned new ostream inclusion
namespace {
template<typename X>
struct use_StringConversion
{
enum { value = can_convertToString<X>::value
&& !can_lexical2string<X>::value
};
};
template<typename X>
struct use_ObjectTypeIndicator
: __and_<__not_<can_convertToString<X>>
,__not_<can_lexical2string<X>>
,std::is_object<X>
>
{ };
}
template<typename X, typename = enable_if<use_StringConversion<X>>>
std::ostream&
operator<< (std::ostream& os, X const& obj)
{
return os << CustomStringConv<X>::invoke (obj);
}
//
// template<typename X, typename = enable_if<use_ObjectTypeIndicator<X>>>
// std::ostream&
// operator<< (std::ostream& os, X const& obj)
// {
// return os << CustomStringConv<X>::invoke (obj);
// }
template<typename X>
std::ostream&
operator<< (std::ostream& os, P<X> const& ptr)
{
return os << stringz (ptr);
}
/////////////////////////////////////////planned new ostream inclusion
int
main (int, char**)
{
auto psss = newP<Reticent>();
auto gnng = newP<GenNode>("Hui", "Buh");
cout << "uiii..." << stringz(psss) <<endl;
cout << "maui..." << stringz(gnng) <<endl;
#define SHOW_CHECK(_EXPR_) cout << STRINGIFY(_EXPR_) << "\t : " << (_EXPR_::value? "Yes":"No") << endl;
using CharLit = typeof("bla");
using BasicallyString = is_basically<CharLit, string>;
using BasicallyChar = is_basically<std::remove_all_extents<CharLit>::type, char>;
SHOW_CHECK (BasicallyChar);
SHOW_CHECK (BasicallyString);
SHOW_CHECK (std::is_arithmetic<CharLit>);
SHOW_CHECK (can_lexical2string<CharLit>);
SHOW_CHECK (can_convertToString<CharLit>);
SHOW_CHECK (use_StringConversion<CharLit>);
cout << "mauu..." << psss <<endl;
cout << "wauu..." << gnng <<endl;
// cout << "mauuu.." << *psss <<endl; ///////////does not compile (but error message is misleading)
cout << "wauuu.." << *gnng <<endl;
cout << "\n.gulp.\n";

View file

@ -348,7 +348,10 @@ namespace asset {
ID<KIND> ID<KIND>::INVALID = ID(0);
/** convenient for debugging */
/** convenient for debugging
* @deprecated to be obsoleted by automatically using
* custom string conversion in ostreams
*/
inline string str (PcAsset const& a)
{
if (a)

View file

@ -184,7 +184,7 @@ namespace control {
ostream&
dump (ostream& output) const
{
return BASE::dump (output << util::str (element()) << ',');
return BASE::dump (output << util::str (element()) << ','); //////////////////TICKET #985 : make str obsolete!
}
friend bool

View file

@ -61,7 +61,7 @@ namespace asset {
else
{
_Fmt fmt("%s %|50T.| id=%s adr=%p smart-ptr=%p use-count=%u");
cout << fmt % str(aa) % aa->getID() % aa.get() % &aa % (aa.use_count() - 1) << "\n";
cout << fmt % str(aa) % aa->getID() % aa.get() % &aa % (aa.use_count() - 1) << "\n"; ////////////TICKET #985 : make str obsolete
} }

View file

@ -122,7 +122,7 @@ namespace test {
CHECK (com);
CHECK (com == Command::get("test.command1.2"));
CHECK (contains (str(com), "test.command1.2"));
CHECK (contains (str(com), "{def}"));
CHECK (contains (str(com), "{def}")); //////////////////TICKET #985 : make str obsolete!
CHECK (!com.canExec());
VERIFY_ERROR (UNBOUND_ARGUMENTS, com() );
CHECK ( 0 == command1::check_);

View file

@ -73,7 +73,7 @@ namespace test {
void treat (Clip& c)
{
Placement<Clip>& pC = getPlacement<Clip>();
cout << "Clip on media : "<< str(pC->getMedia()) <<"\n";
cout << "Clip on media : "<< str(pC->getMedia()) <<"\n"; //////////////////TICKET #985 : make str obsolete!
CHECK (pC->operator==(c));
log_ = string (pC);
}

View file

@ -199,7 +199,7 @@ namespace test {
// access MObject (Clip API)
// cout << rMO->operator string() << endl; /////////////////////TICKET #428
PMedia media = rMO->getMedia();
cout << str(media) << endl; /////////////////////TICKET #520
cout << str(media) << endl; /////////////////////TICKET #520 ///////TICKET #985 : make str obsolete!
Duration mediaLength = media->getLength();
CHECK (!isnil (mediaLength));
CHECK (rMO->isValid());