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/typelist.hpp"
|
||||||
#include "lib/meta/typelistutil.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 typelist
|
||||||
|
|
||||||
} // namespace lumiera
|
} // namespace lumiera
|
||||||
|
|
|
||||||
|
|
@ -38,48 +38,152 @@
|
||||||
#include "lib/meta/typelist.hpp" ////////////TODO really?
|
#include "lib/meta/typelist.hpp" ////////////TODO really?
|
||||||
#include "lib/meta/tuple.hpp"
|
#include "lib/meta/tuple.hpp"
|
||||||
#include "meta/typelist-diagnostics.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>
|
#include <iostream>
|
||||||
|
|
||||||
using ::test::Test;
|
using ::test::Test;
|
||||||
|
|
||||||
|
using boost::enable_if;
|
||||||
|
using boost::format;
|
||||||
|
using boost::str;
|
||||||
|
using util::unConst;
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::cout;
|
using std::cout;
|
||||||
|
using std::endl;
|
||||||
|
|
||||||
|
|
||||||
namespace lumiera {
|
namespace lumiera {
|
||||||
namespace typelist{
|
namespace typelist{
|
||||||
namespace test {
|
namespace test {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace { // test data
|
namespace { // test data
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef Types< Num<1>
|
typedef Types< Num<1>
|
||||||
, Num<2>
|
|
||||||
, Num<3>
|
, Num<3>
|
||||||
>::List List1;
|
, Num<5>
|
||||||
typedef Types< Num<5>
|
> Types1;
|
||||||
, Num<6>
|
typedef Types< Num<2>
|
||||||
, Num<7>
|
, Num<4>
|
||||||
>::List List2;
|
> Types2;
|
||||||
|
typedef Types< Num<7> > Types3;
|
||||||
|
|
||||||
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; };
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // (End) test data
|
} // (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 //////////////////////////////////////////
|
* @test //////////////////////////////////////////
|
||||||
* - building combinations and permutations
|
* - building combinations and permutations
|
||||||
|
|
@ -89,8 +193,32 @@ namespace test {
|
||||||
virtual void
|
virtual void
|
||||||
run (Arg)
|
run (Arg)
|
||||||
{
|
{
|
||||||
|
check_diagnostics();
|
||||||
|
|
||||||
UNIMPLEMENTED ("verify type tuples");
|
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/typelist.hpp"
|
||||||
#include "lib/meta/generator.hpp"
|
#include "lib/meta/generator.hpp"
|
||||||
|
#include "lib/meta/util.hpp"
|
||||||
|
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
|
#include <boost/utility/enable_if.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
using boost::format;
|
using boost::format;
|
||||||
|
using boost::enable_if;
|
||||||
|
|
||||||
|
|
||||||
namespace lumiera {
|
namespace lumiera {
|
||||||
|
|
@ -54,8 +59,8 @@ namespace typelist{
|
||||||
char o_;
|
char o_;
|
||||||
Numz (char x =0) : o_(x) { }
|
Numz (char x =0) : o_(x) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/** constant-wrapper type for debugging purposes,
|
/** constant-wrapper type for debugging purposes,
|
||||||
* usable for generating lists of distinguishable types
|
* usable for generating lists of distinguishable types
|
||||||
*/
|
*/
|
||||||
|
|
@ -80,7 +85,7 @@ namespace typelist{
|
||||||
struct Config;
|
struct Config;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** helper for generating test lists */
|
/** helper for generating test lists */
|
||||||
template<class X> struct CountDown { typedef NullType List; };
|
template<class X> struct CountDown { typedef NullType List; };
|
||||||
template<> struct CountDown<Num<0> > { typedef Node<Num<0>, 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 test { //< unit tests covering typelist manipulating templates
|
||||||
namespace { // hidden internals for diagnostics....
|
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
|
} // (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
|
}}} // namespace lumiera::typelist::test
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ namespace test {
|
||||||
void
|
void
|
||||||
check_diagnostics ()
|
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;
|
typedef InstantiateChained<List1::List, Printer, NullP > Contents_List1;
|
||||||
cout << "List1" << "\t:" << Contents_List1::print() << "\n";
|
cout << "List1" << "\t:" << Contents_List1::print() << "\n";
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue