From ad7c326c9c3bfc3ba86653c7e47a319172ba0276 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 20 Jun 2009 23:18:02 +0200 Subject: [PATCH] got basic diagnostics for type tuples working --- src/lib/meta/tuple.hpp | 12 ++ src/lib/meta/util.hpp | 18 +++ tests/lib/meta/type-tuple-test.cpp | 164 +++++++++++++++++++++--- tests/lib/meta/typelist-diagnostics.hpp | 44 +++++-- tests/lib/meta/typelist-manip-test.cpp | 2 +- 5 files changed, 210 insertions(+), 30 deletions(-) diff --git a/src/lib/meta/tuple.hpp b/src/lib/meta/tuple.hpp index 4cb0a49d8..e10d86abe 100644 --- a/src/lib/meta/tuple.hpp +++ b/src/lib/meta/tuple.hpp @@ -49,6 +49,7 @@ #include "lib/meta/typelist.hpp" #include "lib/meta/typelistutil.hpp" +#include "lib/meta/util.hpp" @@ -443,6 +444,17 @@ namespace typelist{ } + + /** Trait template for detecting a type tuple */ + template + class is_Tuple + { + template struct Check { typedef No_t It; }; + template struct Check > { typedef Yes_t It; }; + + public: + static const bool value = (sizeof(Yes_t)==sizeof(typename Check::It)); + }; /** diff --git a/src/lib/meta/util.hpp b/src/lib/meta/util.hpp index b01a412fa..f824ee6b6 100644 --- a/src/lib/meta/util.hpp +++ b/src/lib/meta/util.hpp @@ -70,6 +70,24 @@ namespace lumiera { }; + /** Trait template for detecting a typelist type. + * For example, this allows to write specialisations with the help of + * boost::enable_if + */ + template + class is_Typelist + { + template + static Yes_t check(typename X::List *); + template + static No_t check(...); + + public: + static const bool value = (sizeof(Yes_t)==sizeof(check(0))); + }; + + + } // namespace typelist } // namespace lumiera diff --git a/tests/lib/meta/type-tuple-test.cpp b/tests/lib/meta/type-tuple-test.cpp index a8f6b13dc..b0e045582 100644 --- a/tests/lib/meta/type-tuple-test.cpp +++ b/tests/lib/meta/type-tuple-test.cpp @@ -38,48 +38,152 @@ #include "lib/meta/typelist.hpp" ////////////TODO really? #include "lib/meta/tuple.hpp" #include "meta/typelist-diagnostics.hpp" -//#include "lib/util.hpp" +#include "lib/util.hpp" -//#include +#include +#include #include using ::test::Test; + +using boost::enable_if; +using boost::format; +using boost::str; +using util::unConst; using std::string; using std::cout; +using std::endl; namespace lumiera { namespace typelist{ namespace test { + namespace { // test data typedef Types< Num<1> - , Num<2> , Num<3> - >::List List1; - typedef Types< Num<5> - , Num<6> - , Num<7> - >::List List2; - - - template struct CountDown { typedef NullType List; }; - template<> struct CountDown > { typedef Node, NullType> List; }; - template struct CountDown > { typedef Node, typename CountDown >::List> List; }; + , Num<5> + > Types1; + typedef Types< Num<2> + , Num<4> + > Types2; + typedef Types< Num<7> > Types3; } // (End) test data + + + 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_)); + } + + 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) {} + + + protected: + + 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 + string + showDump (Tuple const& tuple) + { + typedef BuildTupleAccessor BuildAccessor; + typedef typename BuildAccessor::Accessor Displayer; + + return " Tup" + Displayer(tuple).dump(); + } + + template + typename enable_if< is_Tuple, + string >::type + showType () + { + typedef InstantiateChained DumpPrinter; + return "TYPES-<>" + + DumpPrinter::print(); + } + + // see the macros DISPLAY and DUMPVAL defined in typelist-diagnostics.hpp + + + + + /************************************************************************* * @test ////////////////////////////////////////// * - building combinations and permutations @@ -89,8 +193,32 @@ namespace test { virtual void run (Arg) { + check_diagnostics(); + UNIMPLEMENTED ("verify type tuples"); } + + + /** verify the test input data + * @see TypeListManipl_test#check_diagnostics() + * for an explanation of the DISPLAY macro + */ + void + check_diagnostics () + { + typedef Types1::List L1; + typedef Types2::List L2; + typedef Types3::List L3; + + DISPLAY (L1); + DISPLAY (L2); + DISPLAY (L3); + + typedef Tuple Tup3; + + DISPLAY (Tup3); + DUMPVAL (Tup3()); + } }; diff --git a/tests/lib/meta/typelist-diagnostics.hpp b/tests/lib/meta/typelist-diagnostics.hpp index c5bdd94a2..201c1f4fd 100644 --- a/tests/lib/meta/typelist-diagnostics.hpp +++ b/tests/lib/meta/typelist-diagnostics.hpp @@ -38,11 +38,16 @@ #include "lib/meta/typelist.hpp" #include "lib/meta/generator.hpp" +#include "lib/meta/util.hpp" #include +#include + + using std::string; using boost::format; +using boost::enable_if; namespace lumiera { @@ -54,8 +59,8 @@ namespace typelist{ char o_; Numz (char x =0) : o_(x) { } }; - - + + /** constant-wrapper type for debugging purposes, * usable for generating lists of distinguishable types */ @@ -80,7 +85,7 @@ namespace typelist{ struct Config; - + /** helper for generating test lists */ template struct CountDown { typedef NullType List; }; template<> struct CountDown > { typedef Node, NullType> List; }; @@ -88,6 +93,7 @@ namespace typelist{ + namespace test { //< unit tests covering typelist manipulating templates namespace { // hidden internals for diagnostics.... @@ -165,17 +171,33 @@ namespace typelist{ }; -#define DIAGNOSE(LIST) \ - typedef InstantiateChained Contents_##LIST; - -#define DISPLAY(NAME) \ - DIAGNOSE(NAME); cout << STRINGIFY(NAME) << "\t:" << Contents_##NAME::print() << "\n"; - - - } // (End) internal defs + /* ===== printing types and contents ===== */ + + template + typename enable_if< is_Typelist, + string >::type + showType () + { + typedef InstantiateChained DumpPrinter; + return DumpPrinter::print(); + } + + // Note: we define overloads of this function for other types, especially Tuples + + +#define DISPLAY(NAME) \ + cout << STRINGIFY(NAME) << "\t:" << showType() << "\n"; + +#define DUMPVAL(NAME) \ + cout << STRINGIFY(NAME) << "\t:" << showDump (NAME) << "\n"; + + + + + }}} // namespace lumiera::typelist::test #endif diff --git a/tests/lib/meta/typelist-manip-test.cpp b/tests/lib/meta/typelist-manip-test.cpp index 3f742ba6c..f3096430e 100644 --- a/tests/lib/meta/typelist-manip-test.cpp +++ b/tests/lib/meta/typelist-manip-test.cpp @@ -108,7 +108,7 @@ namespace test { void check_diagnostics () { - // Explanation: the DISPLAY macro expands as follows.... + // Explanation: the DISPLAY macro results in the following definition.... typedef InstantiateChained Contents_List1; cout << "List1" << "\t:" << Contents_List1::print() << "\n";