Comparison with no explicit member template
arguments and no template template parameter
struct WrappedLess
{
template<class T> struct Impl
{
typedef std::less<T> type;
};
};
template<class ValueCmp = WrappedLess> class CompareRecord
{
public:
CompareRecord():resultKnown_(false),everyThingTested_(false),result_(false){};
// was useful for printing base classes - and may be useful for
// other binary traversions - only here it cannot do something
// meaningful.
template<class ReflectedClass> void
operator()(const ReflectedClass&, const ReflectedClass&)
{/* no op*/}
// here ValueType is neither compiletime- nor runtime iterable.
// Hence it can be compared "as is" or the user has to define an
// operator<(const ValueType& lhs, const ValueType& rhs)
template<class WrappedScope, class NameTag, class ValueType>
void operator()(const ValueType& lhsValue,const ValueType& rhsValue,
NameTag,WrappedScope, WrappedScope)
{
typedef typename ValueCmp::template Impl<ValueType>::type Comparison;
if(!resultKnown_)
{
Comparison cmp;
result_ = cmp(lhsValue, rhsValue);
resultKnown_ = result_ || // lhs precedes rhs
cmp(rhsValue,lhsValue); // rhs precedes lhs
}
}
private:
template<class WrappedScope, class NameTag, class ValueType>
void missingPartialOrdering(const ValueType&,const ValueType&,
NameTag,WrappedScope, WrappedScope,LeaveAttributeTag)
{
typedef typename WrappedScope::type Scope;
enum {lastAttribute = Scope::AttributePos<NameTag,Scope::ThisClass>::value == Scope::NumAttributes - 1};
// in a nested structure of reflected classes this may be true when
// in the outermost class still attributes are to check.
// This is no problem as long as no attempt is made to treat the comparison
// result at that stage as a comparison result for the outermost class.
everyThingTested_ = lastAttribute;
};
template<class WrappedScope, class NameTag, class ValueType>
void missingPartialOrdering(const ValueType&,const ValueType&,
NameTag,WrappedScope, WrappedScope,int /* not leaving an attribute*/)
{/* no op*/}
public:
template<class WrappedScope, class NameTag, class ValueType, class GraphEvent>
void operator()(const ValueType& lhsValue,const ValueType& rhsValue,NameTag attributeTag,
GraphEvent,WrappedScope lhsScope, WrappedScope rhsScope)
{
enum {leaveAttribute = boost::is_same<GraphEvent,
LeaveAttributeTag>::value};
typedef typename boost::ct_if<(leaveAttribute == 0),
int,
LeaveAttributeTag>::type
type;
missingPartialOrdering(lhsValue, rhsValue, attributeTag, lhsScope, rhsScope, type());
}
// lhs collection ran out of bullets
template<class WrappedScope, class NameTag, class ValueIter>
void operator()(PastEndTag,ValueIter /* rhsPos */,ValueIter /* rhsEnd */,
NameTag,WrappedScope, WrappedScope)
{
if(!resultKnown_)
{
// lexicographical sort: "a" < "aa"
result_ = true;
resultKnown_ = true;
}
}
// rhs collection ran out of bullets
template<class WrappedScope, class NameTag, class ValueIter>
void operator()(ValueIter/* lhsPos */,ValueIter /* lhsEnd */, PastEndTag,
NameTag,WrappedScope, WrappedScope)
{
if(!resultKnown_)
{
// lexicographical sort: "a" < "aa"
result_ = false;
resultKnown_ = true;
}
}
// lhs is a null pointer and rhs was not - hence it could be dereferenced
template<class WrappedScope, class NameTag, class ValueType>
void operator()(PastEndTag,const ValueType& /*rhsValue*/,
NameTag,WrappedScope, WrappedScope)
{
if(!resultKnown_)
{
// lexicographical sort: "a" < "aa"
result_ = true;
resultKnown_ = true;
}
}
// rhs is a null pointer and lhs was not - hence it could be dereferenced
template<class WrappedScope, class NameTag, class ValueType>
void operator()(const ValueType& /*lhsValue*/,PastEndTag,
NameTag,WrappedScope, WrappedScope)
{
if(!resultKnown_)
{
// lexicographical sort: "a" < "aa"
result_ = false;
resultKnown_ = true;
}
}
bool result()
{
if(!resultKnown_ && !everyThingTested_)
throw std::logic_error("trying to access an undefined comparison result");
return result_;
}
// a nested DoneTag type is needed to be able to detect conditional traversion end
// with MSVC6 (sorry for that).
// (once the traversion has reached attributes with non-equivalent values (with
// respect to the comparison ValueCmp::Impl<T>::type) you might want to end
// the traversion)
typedef int DoneTag;
bool done()const
{
return resultKnown_;
}
private:
bool everyThingTested_;
bool result_;
bool resultKnown_;
};
template<class Record> inline bool recordIsLess(const Record& lhs,
const Record& rhs)
{
CompareRecord<> comparison;
depthFirstForeachIncAllBaseClasses(lhs, rhs, comparison, InstanceVariableTag());
return comparison.result();
};
Last revised: September 13, 2004 |
Copyright © 2004 Arne Adams |