got basic diagnostics for type tuples working
This commit is contained in:
parent
294c254f29
commit
ad7c326c9c
5 changed files with 210 additions and 30 deletions
|
|
@ -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<typename TUP>
|
||||
class is_Tuple
|
||||
{
|
||||
template<class X> struct Check { typedef No_t It; };
|
||||
template<class TY> struct Check<Tuple<TY> > { typedef Yes_t It; };
|
||||
|
||||
public:
|
||||
static const bool value = (sizeof(Yes_t)==sizeof(typename Check<TUP>::It));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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<typename TY>
|
||||
class is_Typelist
|
||||
{
|
||||
template<class X>
|
||||
static Yes_t check(typename X::List *);
|
||||
template<class>
|
||||
static No_t check(...);
|
||||
|
||||
public:
|
||||
static const bool value = (sizeof(Yes_t)==sizeof(check<TY>(0)));
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace typelist
|
||||
|
||||
} // namespace lumiera
|
||||
|
|
|
|||
|
|
@ -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 <boost/format.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <iostream>
|
||||
|
||||
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<class X> struct CountDown { typedef NullType List; };
|
||||
template<> struct CountDown<Num<0> > { typedef Node<Num<0>, NullType> List; };
|
||||
template<int I> struct CountDown<Num<I> > { typedef Node<Num<I>, typename CountDown<Num<I-1> >::List> List; };
|
||||
, Num<5>
|
||||
> Types1;
|
||||
typedef Types< Num<2>
|
||||
, Num<4>
|
||||
> Types2;
|
||||
typedef Types< Num<7> > Types3;
|
||||
|
||||
|
||||
|
||||
} // (End) test data
|
||||
|
||||
|
||||
namespace { // Diagnostics
|
||||
|
||||
|
||||
|
||||
template<int i>
|
||||
string
|
||||
showTupElement(Num<i> o)
|
||||
{
|
||||
static format constElm("(%i)");
|
||||
static format changedElm("{%i}");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return str ( (o.o_==i? constElm:changedElm) % int(o.o_));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
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<idx>(); }
|
||||
TY const& element() const { return unConst(this)->template getAt<idx>(); }
|
||||
|
||||
public:
|
||||
TupleElementDisplayer(TUP const& tuple) : BASE(tuple) {}
|
||||
|
||||
string
|
||||
dump (string const& prefix = "(") const
|
||||
{
|
||||
return BASE::dump (prefix+showTupElement(element())+",");
|
||||
}
|
||||
};
|
||||
|
||||
template<class TUP>
|
||||
class TupleElementDisplayer<NullType, TUP, TUP, 0>
|
||||
: 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<typename TYPES>
|
||||
string
|
||||
showDump (Tuple<TYPES> const& tuple)
|
||||
{
|
||||
typedef BuildTupleAccessor<TYPES,TupleElementDisplayer> BuildAccessor;
|
||||
typedef typename BuildAccessor::Accessor Displayer;
|
||||
|
||||
return " Tup" + Displayer(tuple).dump();
|
||||
}
|
||||
|
||||
template<typename TUP>
|
||||
typename enable_if< is_Tuple<TUP>,
|
||||
string >::type
|
||||
showType ()
|
||||
{
|
||||
typedef InstantiateChained<typename TUP::ArgList, Printer, NullP> 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<Types3> Tup3;
|
||||
|
||||
DISPLAY (Tup3);
|
||||
DUMPVAL (Tup3());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -38,11 +38,16 @@
|
|||
|
||||
#include "lib/meta/typelist.hpp"
|
||||
#include "lib/meta/generator.hpp"
|
||||
#include "lib/meta/util.hpp"
|
||||
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
|
||||
|
||||
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<class X> struct CountDown { typedef NullType List; };
|
||||
template<> struct CountDown<Num<0> > { typedef Node<Num<0>, 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<LIST::List, Printer, NullP> Contents_##LIST;
|
||||
|
||||
#define DISPLAY(NAME) \
|
||||
DIAGNOSE(NAME); cout << STRINGIFY(NAME) << "\t:" << Contents_##NAME::print() << "\n";
|
||||
|
||||
|
||||
|
||||
} // (End) internal defs
|
||||
|
||||
|
||||
|
||||
/* ===== printing types and contents ===== */
|
||||
|
||||
template<typename TYPES>
|
||||
typename enable_if< is_Typelist<TYPES>,
|
||||
string >::type
|
||||
showType ()
|
||||
{
|
||||
typedef InstantiateChained<typename TYPES::List, Printer, NullP> DumpPrinter;
|
||||
return DumpPrinter::print();
|
||||
}
|
||||
|
||||
// Note: we define overloads of this function for other types, especially Tuples
|
||||
|
||||
|
||||
#define DISPLAY(NAME) \
|
||||
cout << STRINGIFY(NAME) << "\t:" << showType<NAME>() << "\n";
|
||||
|
||||
#define DUMPVAL(NAME) \
|
||||
cout << STRINGIFY(NAME) << "\t:" << showDump (NAME) << "\n";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}}} // namespace lumiera::typelist::test
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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<List1::List, Printer, NullP > Contents_List1;
|
||||
cout << "List1" << "\t:" << Contents_List1::print() << "\n";
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue