/* TUPLE-DIAGNOSTICS - helper for diagnostics of type tuples Copyright (C) Lumiera.org 2009, Hermann Vosseler 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 tuple-diagnostics.hpp ** an extension to typelist-diagnostics.hpp, allowing to dump the \em contents ** of a Tuple datatype. Any type defining an operator string() may be printed ** when used as Tuple member type; special formatting is provided for the ** Num test types, which makes typelist and tuples of these types ** a good candidate for unit tests. ** ** @see type-tuple-test.cpp ** @see typelist-manip-test.cpp ** */ #ifndef META_TUPLE_DIAGNOSTICS_H #define META_TUPLE_DIAGNOSTICS_H #include "meta/typelist-diagnostics.hpp" #include "lib/meta/tuple.hpp" #include #include #include #include using std::string; using boost::str; using boost::format; using boost::enable_if; using boost::lexical_cast; using util::unConst; namespace lib { namespace meta { namespace test { namespace { // Diagnostics template string showTupElement(Num o) { static format constElm("(%i)"); static format changedElm("{%i}"); return str ( (o.o_==i? constElm:changedElm) % int(o.o_)); } string showTupElement(int i) { return lexical_cast(i); } template string showTupElement(T x) { return string(x); } /** * Helper template which acts as an "accessor". * Using the BuildTupleAccessor, we create a linear chain * of such TupleElementDisplayers as subclass of a given tuple type. * Here this technique is just used for dumping the tuples data fields, * but e.g. the control::Closure uses the same principle for manipulating * the individual datafields of an function argument tuple. */ template < typename TY , class BASE , class TUP , uint idx > class TupleElementDisplayer : public BASE { TY & element() { return BASE::template getAt(); } TY const& element() const { return unConst(this)->template getAt(); } public: TupleElementDisplayer(TUP const& tuple) : BASE(tuple) {} string dump (string const& prefix ="(") const { return BASE::dump (prefix+showTupElement(element())+","); } }; template class TupleElementDisplayer : public TUP { public: TupleElementDisplayer(TUP const& tuple) : TUP(tuple) {} string dump (string const& prefix ="(") const { if (1 < prefix.length()) // removing the trailing comma return prefix.substr (0, prefix.length()-1) +")"; else return prefix+")"; } }; } // (END) Diagnostics Helper /* ===== printing Tuple types and contents ===== */ template typename enable_if< is_TuplePlain >, string >::type showDump (Tuple const& tuple) { typedef BuildTupleAccessor BuildAccessor; typedef typename BuildAccessor::Accessor Displayer; return "...Tuple" + Displayer(tuple).dump(); } template typename enable_if< is_TupleListType >, string >::type showDump (Tuple const& tuple) { typedef typename Tuple::Type TypeSeq; Tuple plainTuple (tuple); typedef BuildTupleAccessor BuildAccessor; typedef typename BuildAccessor::Accessor Displayer; return "...Tuple" + Displayer(plainTuple).dump(); } template typename enable_if< is_TuplePlain, string >::type showType () { typedef InstantiateChained DumpPrinter; return "TYPES-<>" + DumpPrinter::print(); } template typename enable_if< is_TupleListType, string >::type showType () { typedef InstantiateChained DumpPrinter; return "TYPES-[]" + DumpPrinter::print(); } // see the macros DISPLAY and DUMPVAL defined in typelist-diagnostics.hpp }}} // namespace lib::meta::test #endif