Re: Metaprogramming: Tool or toy? Case study: A law based test automaton
Thank you all for your valuable comments and suggestions.
Removing virtual functions using the curiously recurring
template pattern as suggested by Giovanni P. Deretta
reduced code size by about 20% but had no effect on
compilation times. (Thank you for that! Since I have
not had much experience with the pattern I did learn
a lot :)
'Replacing' Loki by MPL/Fusion is hardly applicable,
because I used only tiny parts of Loki library code:
Typelist and related Typelist-Macros.
What I did use was the idea of Typelist generated
classes namely my own adaption of GenScatteredHirarchy,
which is still a little simpler than the original.
//-----------------------------------------------------
namespace tup {
template <class TList, unsigned int index> struct TupleGentor;
template <class HeadT, class TailT, unsigned int index>
struct TupleGentor<Typelist<HeadT, TailT>, index>
: public TupleElement<HeadT, index>
, public TupleGentor<TailT, index+1>
{
typedef Typelist<HeadT, TailT> TList;
typedef TupleElement<HeadT, index> HeadClass;
typedef TupleGentor<TailT, index+1> TailClass;
};
template <unsigned int size>
class TupleGentor<NullType, size>
{ typedef NullType TList; };
....
// class templates along the recursive structure of
// TupleGentor using partial instantiaton e.g.
template <...> TemplateMapper;
}
Based on this tuple generator class I defined the
central static polymorphical tuple class:
template <typename Types> class tuple
: public tup::TupleGentor<Types, 0>
{
public:
enum { Size = TL::Length<Types>::value };
...
template
<
template<class>class UnaryTpl,
template<typename,template<class>class>class Fun,
class TrgTupleT
>
void map_template(TrgTupleT& target)
{
tup::TemplateMapper<UnaryTpl, Fun, TrgTupleT, SelfType>
::Do(target, *this);
}
...
}
//-----------------------------------------------------
Now for any Typelist based tuple of a Law's input variables
LawT::input_tuple input;
the corresponding tuple of value generators is computed via
metaprogramming at compile time.
typedef typename
MapType<GentorT, input_types>::Result gentor_types;
typedef typename tuple<gentor_types> input_gentor;
input_gentor _gentors;
In a LawValidater's run the types of the Law's instance
tuple determines the types of the corresponding value
generators:
template <class LawT, template<typename>class GentorT>
void LawValidater<LawT, GentorT>::run()
{
LawT::input_tuple values;
for(int idx=0; idx<_trialsCount; idx++)
{
...
// 'map_template' maps a value generator template to each
// component of the tuple 'values' and applies the functor
// class 'SomeValues', generating a new instance for the law
_gentor.template map_template<GentorT, SomeValue>(values);
_law.setInstance(values);
if(!_law.holds())
_lawViolations.insert(_law);
}
}
The matching and handling of a Law's instance types to
value generators, string representers and things like
that is all done via functional style recursive metaprogramming
like e.g. for
template <...> TemplateMapper;
that follows the recursive term structure of class TupleGentor.
I can not quite see how MPL can be helpful here.
ciao
Joachim
--
The code of LaBatea is inculded in the the
'Interval Template Library (ITL)' that can be downloaded from
http://sourceforge.net/projects/itl. Documentaion and performance
charts are availabel from http://www.herold-faulhaber.de/itl/
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]