Library: investigate further ramifications and clean-up Itertools
The detailed analysis of corner cases indicated a lot of hidden dangers when stretching the `IterExplorer` design beyond its limits. By deliberate choice, this design was kept open so that advanced cohesive implementation structures can be built. It is even possible ''and tolerated'' to rely on ''references'' to some degree -- assuming however that the referred memory location remains stable. As it turned out, these basic assumptions can be broken by a combination of read-ahead processing (as is necessary for grouping and filtering), together with adaptor objects embedded as value, especially when the resulting pipeline object is then moved or copied during evaluation. While my general attitude towards such extremely clever implementation constructs is "don't shoot yourself into your foot unless you need to" -- it seems prudent to clean-up some crappy code from the first attempts towards an iterator pipeline -- notably some of the »Itertools«.
This commit is contained in:
parent
40d3167d1a
commit
a835a796b2
28 changed files with 2328 additions and 1331 deletions
|
|
@ -44,7 +44,7 @@
|
||||||
using util::join;
|
using util::join;
|
||||||
using boost::lexical_cast;
|
using boost::lexical_cast;
|
||||||
using lib::time::TimeValue;
|
using lib::time::TimeValue;
|
||||||
using lib::transformIterator;
|
using lib::transformIter;
|
||||||
using util::almostEqual;
|
using util::almostEqual;
|
||||||
using lib::hash::LuidH;
|
using lib::hash::LuidH;
|
||||||
|
|
||||||
|
|
@ -297,9 +297,9 @@ namespace diff{
|
||||||
|
|
||||||
return (Rec::TYPE_NIL==rec.getType()? "" : rec.getType())
|
return (Rec::TYPE_NIL==rec.getType()? "" : rec.getType())
|
||||||
+ "{"
|
+ "{"
|
||||||
+ join (transformIterator (rec.attribs(), renderAttrib))
|
+ join (transformIter (rec.attribs(), renderAttrib))
|
||||||
+ (isnil(rec.scope())? "" : "|")
|
+ (isnil(rec.scope())? "" : "|")
|
||||||
+ join (transformIterator (rec.scope() , renderChild))
|
+ join (transformIter (rec.scope() , renderChild))
|
||||||
+ "}"
|
+ "}"
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -375,8 +375,6 @@ namespace diff{
|
||||||
iterator end() const;
|
iterator end() const;
|
||||||
|
|
||||||
|
|
||||||
using ChildDataIter = TransformIter<Rec::scopeIter, DataCap const&>;
|
|
||||||
|
|
||||||
/** visit the _data_ of nested child elements
|
/** visit the _data_ of nested child elements
|
||||||
* @return an iterator over the DataCap elements of all children,
|
* @return an iterator over the DataCap elements of all children,
|
||||||
* in case this GenNode actually holds a Record.
|
* in case this GenNode actually holds a Record.
|
||||||
|
|
@ -384,26 +382,26 @@ namespace diff{
|
||||||
* @note this iterator visits _only_ the children, which are
|
* @note this iterator visits _only_ the children, which are
|
||||||
* by definition unnamed. It does _not_ visit attributes.
|
* by definition unnamed. It does _not_ visit attributes.
|
||||||
*/
|
*/
|
||||||
friend ChildDataIter
|
friend auto
|
||||||
childData (GenNode const& n)
|
childData (GenNode const& n)
|
||||||
{
|
{
|
||||||
return ChildDataIter{ n.data.childIter()
|
return transformIter(n.data.childIter()
|
||||||
,[](GenNode const& child) ->DataCap const&
|
,[](GenNode const& child) ->DataCap const&
|
||||||
{
|
{
|
||||||
return child.data;
|
return child.data;
|
||||||
}
|
}
|
||||||
};
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend ChildDataIter
|
friend auto
|
||||||
childData (Rec::scopeIter&& scopeIter)
|
childData (Rec::scopeIter&& scopeIter)
|
||||||
{
|
{
|
||||||
return ChildDataIter{ std::forward<Rec::scopeIter>(scopeIter)
|
return transformIter(std::forward<Rec::scopeIter>(scopeIter)
|
||||||
,[](GenNode const& child) ->DataCap const&
|
,[](GenNode const& child) ->DataCap const&
|
||||||
{
|
{
|
||||||
return child.data;
|
return child.data;
|
||||||
}
|
}
|
||||||
};
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -308,8 +308,6 @@ namespace diff{
|
||||||
|
|
||||||
using iterator = IterAdapter<ElmIter, const Record*>;
|
using iterator = IterAdapter<ElmIter, const Record*>;
|
||||||
using scopeIter = iter_stl::_SeqT<const Storage>::Range;
|
using scopeIter = iter_stl::_SeqT<const Storage>::Range;
|
||||||
using keyIter = TransformIter<scopeIter, string>;
|
|
||||||
using valIter = TransformIter<scopeIter, Access>;
|
|
||||||
|
|
||||||
/** default iteration exposes all data within this "object", starting with the attributes */
|
/** default iteration exposes all data within this "object", starting with the attributes */
|
||||||
iterator begin () const { return iterator(this, attribs_.empty()? children_.begin() : attribs_.begin()); }
|
iterator begin () const { return iterator(this, attribs_.empty()? children_.begin() : attribs_.begin()); }
|
||||||
|
|
@ -318,8 +316,8 @@ namespace diff{
|
||||||
scopeIter attribs() const { return iter_stl::eachElm (attribs_); }
|
scopeIter attribs() const { return iter_stl::eachElm (attribs_); }
|
||||||
scopeIter scope() const { return iter_stl::eachElm (children_); }
|
scopeIter scope() const { return iter_stl::eachElm (children_); }
|
||||||
|
|
||||||
keyIter keys() const { return transformIterator(attribs(), extractKey); }
|
auto keys() const { return transformIter (attribs(), extractKey); }
|
||||||
valIter vals() const { return transformIterator(attribs(), extractVal); }
|
auto vals() const { return transformIter (attribs(), extractVal); }
|
||||||
|
|
||||||
protected: /* ==== API for the IterAdapter ==== */
|
protected: /* ==== API for the IterAdapter ==== */
|
||||||
|
|
||||||
|
|
@ -792,11 +790,11 @@ namespace diff{
|
||||||
Record<VAL>::operator std::string() const
|
Record<VAL>::operator std::string() const
|
||||||
{
|
{
|
||||||
using util::join;
|
using util::join;
|
||||||
using lib::transformIterator;
|
using lib::transformIter;
|
||||||
|
|
||||||
return "Rec("
|
return "Rec("
|
||||||
+ (TYPE_NIL==type_? "" : type_)
|
+ (TYPE_NIL==type_? "" : type_)
|
||||||
+ (isnil(this->attribs())? "" : "| "+join (transformIterator (this->attribs(), renderAttribute))+" ")
|
+ (isnil(this->attribs())? "" : "| "+join (transformIter (this->attribs(), renderAttribute))+" ")
|
||||||
+ (isnil(this->scope())? "" : "|{"+join (this->scope())+"}")
|
+ (isnil(this->scope())? "" : "|{"+join (this->scope())+"}")
|
||||||
+ ")"
|
+ ")"
|
||||||
;
|
;
|
||||||
|
|
|
||||||
|
|
@ -110,12 +110,12 @@ namespace diff{
|
||||||
renderRecord (Rec const& record)
|
renderRecord (Rec const& record)
|
||||||
{
|
{
|
||||||
using util::join;
|
using util::join;
|
||||||
using lib::transformIterator;
|
using lib::transformIter;
|
||||||
|
|
||||||
return "Rec("
|
return "Rec("
|
||||||
+ (Rec::TYPE_NIL==record.getType()? "" : record.getType())
|
+ (Rec::TYPE_NIL==record.getType()? "" : record.getType())
|
||||||
+ (isnil(record.attribs())? "" : "| "+join (transformIterator (record.attribs(), renderAttribute))+" ")
|
+ (isnil(record.attribs())? "" : "| "+join (transformIter (record.attribs(), renderAttribute))+" ")
|
||||||
+ (isnil(record.scope())? "" : "|{"+join (transformIterator (record.scope(), renderChild))+"}")
|
+ (isnil(record.scope())? "" : "|{"+join (transformIter (record.scope(), renderChild))+"}")
|
||||||
+ ")"
|
+ ")"
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
@ -289,14 +289,14 @@ namespace diff{
|
||||||
string
|
string
|
||||||
showContent () const
|
showContent () const
|
||||||
{
|
{
|
||||||
return join (transformIterator (begin(), renderNode));
|
return join (transformIter (begin(), renderNode));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** render elements waiting in source buffer to be accepted */
|
/** render elements waiting in source buffer to be accepted */
|
||||||
string
|
string
|
||||||
showSrcBuffer () const
|
showSrcBuffer () const
|
||||||
{
|
{
|
||||||
return join (transformIterator (eachElm(prev_content_), renderNode));
|
return join (transformIter (eachElm(prev_content_), renderNode));
|
||||||
}
|
}
|
||||||
|
|
||||||
EventMatch
|
EventMatch
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,7 @@
|
||||||
#include "lib/error.hpp"
|
#include "lib/error.hpp"
|
||||||
#include "lib/nocopy.hpp"
|
#include "lib/nocopy.hpp"
|
||||||
#include "lib/meta/trait.hpp"
|
#include "lib/meta/trait.hpp"
|
||||||
|
#include "lib/meta/function.hpp"
|
||||||
#include "lib/diff/gen-node.hpp"
|
#include "lib/diff/gen-node.hpp"
|
||||||
#include "lib/diff/tree-mutator.hpp"
|
#include "lib/diff/tree-mutator.hpp"
|
||||||
#include "lib/iter-adapter-stl.hpp"
|
#include "lib/iter-adapter-stl.hpp"
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,7 @@ namespace util {
|
||||||
{
|
{
|
||||||
using Val = lib::meta::ValueTypeBinding<IT>::value_type;
|
using Val = lib::meta::ValueTypeBinding<IT>::value_type;
|
||||||
|
|
||||||
return lib::transformIterator(forward<IT>(src), util::toString<Val>);
|
return lib::transformIter (forward<IT>(src), util::toString<Val>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
** this to the pattern of _type erasure_, where we discard specific
|
** this to the pattern of _type erasure_, where we discard specific
|
||||||
** knowledge after construction; for _such_ cases, opaque-holder.hpp
|
** knowledge after construction; for _such_ cases, opaque-holder.hpp
|
||||||
** might be a better fit.
|
** might be a better fit.
|
||||||
** @see lib::TransformIter
|
** @see lib::iter::Transform
|
||||||
** @see lib::explore
|
** @see lib::explore
|
||||||
**
|
**
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include "lib/meta/util.hpp"
|
#include "lib/meta/util.hpp"
|
||||||
|
#include "lib/meta/function.hpp"
|
||||||
#include "lib/iter-adapter.hpp"
|
#include "lib/iter-adapter.hpp"
|
||||||
#include "lib/itertools.hpp"
|
#include "lib/itertools.hpp"
|
||||||
#include "lib/nocopy.hpp"
|
#include "lib/nocopy.hpp"
|
||||||
|
|
@ -310,7 +311,7 @@ namespace lib {
|
||||||
{
|
{
|
||||||
using Src = std::remove_reference<IT>::type;
|
using Src = std::remove_reference<IT>::type;
|
||||||
using ResVal = lib::meta::_Fun<FUN>::Ret;
|
using ResVal = lib::meta::_Fun<FUN>::Ret;
|
||||||
using TransIter = TransformIter<Src, ResVal>;
|
using TransIter = decltype(lib::transformIter (std::declval<IT>(), std::declval<FUN>()));
|
||||||
using Iter = IterSource<ResVal>::iterator;
|
using Iter = IterSource<ResVal>::iterator;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -326,26 +327,23 @@ namespace lib {
|
||||||
// we can strip the const added by the STL map types
|
// we can strip the const added by the STL map types
|
||||||
using KeyType = std::remove_const<ConstKeyType>::type;
|
using KeyType = std::remove_const<ConstKeyType>::type;
|
||||||
|
|
||||||
using KeyIter = TransformIter<Src, KeyType>;
|
|
||||||
using ValIter = TransformIter<Src, ValType>;
|
|
||||||
|
|
||||||
static KeyType takeFirst (PairType const& pair) { return pair.first; }
|
static KeyType takeFirst (PairType const& pair) { return pair.first; }
|
||||||
static ValType takeSecond(PairType const& pair) { return pair.second;}
|
static ValType takeSecond(PairType const& pair) { return pair.second;}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template<class IT>
|
template<class IT>
|
||||||
_PairIterT<IT>::KeyIter
|
auto
|
||||||
takePairFirst (IT&& source)
|
takePairFirst (IT&& source)
|
||||||
{
|
{
|
||||||
return transformIterator(forward<IT>(source), _PairIterT<IT>::takeFirst );
|
return transformIter (forward<IT>(source), _PairIterT<IT>::takeFirst );
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class IT>
|
template<class IT>
|
||||||
_PairIterT<IT>::ValIter
|
auto
|
||||||
takePairSecond (IT&& source)
|
takePairSecond (IT&& source)
|
||||||
{
|
{
|
||||||
return transformIterator(forward<IT>(source), _PairIterT<IT>::takeSecond );
|
return transformIter (forward<IT>(source), _PairIterT<IT>::takeSecond );
|
||||||
}
|
}
|
||||||
|
|
||||||
} //(END) type helpers...
|
} //(END) type helpers...
|
||||||
|
|
@ -375,10 +373,10 @@ namespace lib {
|
||||||
auto
|
auto
|
||||||
singleVal (VAL&& something)
|
singleVal (VAL&& something)
|
||||||
{
|
{
|
||||||
using Src = decltype(singleValIterator (forward<VAL>(something)));
|
using Src = decltype(singletonIter (forward<VAL>(something)));
|
||||||
using Val = _IterT<Src>::Val;
|
using Val = _IterT<Src>::Val;
|
||||||
|
|
||||||
return IterSource<Val>::build (new WrappedLumieraIter<Src>{singleValIterator (forward<VAL>(something))});
|
return IterSource<Val>::build (new WrappedLumieraIter<Src>{singletonIter (forward<VAL>(something))});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -400,7 +398,7 @@ namespace lib {
|
||||||
|
|
||||||
return IterSource<ValType>::build (
|
return IterSource<ValType>::build (
|
||||||
new WrappedLumieraIter<TransIT> (
|
new WrappedLumieraIter<TransIT> (
|
||||||
transformIterator (forward<IT>(source), processingFunc)));
|
transformIter (forward<IT>(source), processingFunc)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -408,7 +406,7 @@ namespace lib {
|
||||||
* all the keys of the given Map or Hashtable
|
* all the keys of the given Map or Hashtable
|
||||||
*/
|
*/
|
||||||
template<class MAP>
|
template<class MAP>
|
||||||
_MapT<MAP>::KeyIter
|
auto
|
||||||
eachMapKey (MAP& map)
|
eachMapKey (MAP& map)
|
||||||
{
|
{
|
||||||
using Range = RangeIter<typename MAP::iterator>;
|
using Range = RangeIter<typename MAP::iterator>;
|
||||||
|
|
@ -438,13 +436,13 @@ namespace lib {
|
||||||
* the distinct keys
|
* the distinct keys
|
||||||
*/
|
*/
|
||||||
template<class MAP>
|
template<class MAP>
|
||||||
_MapT<MAP>::KeyIter
|
auto
|
||||||
eachDistinctKey (MAP& map)
|
eachDistinctKey (MAP& map)
|
||||||
{
|
{
|
||||||
using Range = RangeIter<typename MAP::iterator>;
|
using Range = RangeIter<typename MAP::iterator>;
|
||||||
|
|
||||||
Range contents (map.begin(), map.end());
|
Range contents (map.begin(), map.end());
|
||||||
return wrapIter (filterRepetitions (takePairFirst(contents)));
|
return wrapIter (filterRepeat (takePairFirst(contents)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -494,6 +494,7 @@ namespace meta {
|
||||||
* @note deliberately a Lumiera iterator does _not fulfil_
|
* @note deliberately a Lumiera iterator does _not fulfil_
|
||||||
* the concept std::input_iterator. And vice versa:
|
* the concept std::input_iterator. And vice versa:
|
||||||
* a STL iterator lacks the `bool` check for iteration end.
|
* a STL iterator lacks the `bool` check for iteration end.
|
||||||
|
* @see IterableClassification_test
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class can_IterForEach
|
class can_IterForEach
|
||||||
|
|
|
||||||
|
|
@ -176,7 +176,7 @@ namespace engine {
|
||||||
auto
|
auto
|
||||||
buildDependencyPlanning()
|
buildDependencyPlanning()
|
||||||
{
|
{
|
||||||
return lib::transformIterator (jobTicket_.getPrerequisites()
|
return lib::transformIter (jobTicket_.getPrerequisites()
|
||||||
,[this](JobTicket& prereqTicket)
|
,[this](JobTicket& prereqTicket)
|
||||||
{
|
{
|
||||||
return JobPlanning{*this, prereqTicket};
|
return JobPlanning{*this, prereqTicket};
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,7 @@ using lib::LUID;
|
||||||
auto
|
auto
|
||||||
getPrerequisites ()
|
getPrerequisites ()
|
||||||
{
|
{
|
||||||
return lib::transformIterator (this->empty()? Prerequisites::iterator()
|
return lib::transformIter (this->empty()? Prerequisites::iterator()
|
||||||
: provision_.prerequisites.begin()
|
: provision_.prerequisites.begin()
|
||||||
,[](Prerequisite& prq) -> JobTicket&
|
,[](Prerequisite& prq) -> JobTicket&
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -395,7 +395,6 @@ namespace session {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
using ElementResolver = function<PlacementMO& (pair<PID,PID> const&)>;
|
|
||||||
mutable ElementResolver elementResolver_;
|
mutable ElementResolver elementResolver_;
|
||||||
|
|
||||||
ElementResolver
|
ElementResolver
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,7 @@
|
||||||
#include "lib/util.hpp"
|
#include "lib/util.hpp"
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
@ -181,7 +182,9 @@ namespace session {
|
||||||
using _PID = PlacementMO::ID;
|
using _PID = PlacementMO::ID;
|
||||||
using ScopeIter = std::unordered_multimap<_PID,_PID>::const_iterator;
|
using ScopeIter = std::unordered_multimap<_PID,_PID>::const_iterator;
|
||||||
using ScopeRangeIter = lib::RangeIter<ScopeIter>;
|
using ScopeRangeIter = lib::RangeIter<ScopeIter>;
|
||||||
using _ID_TableIterator = lib::TransformIter<ScopeRangeIter, PlacementMO&>;
|
using ElementResolver = std::function<PlacementMO& (std::pair<_PID,_PID> const&)>;
|
||||||
|
using _ID_TableIterator = decltype(lib::transformIter(std::declval<ScopeRangeIter>()
|
||||||
|
,std::declval<ElementResolver>()));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ namespace test{
|
||||||
* @note the match also fails, when the given log entry
|
* @note the match also fails, when the given log entry
|
||||||
* has more or less arguments, than the number of
|
* has more or less arguments, than the number of
|
||||||
* given match expressions in `argSeq`
|
* given match expressions in `argSeq`
|
||||||
* @see ExtensibleFilterIter::andFilter()
|
* @see lib::iter_explorer::MutableFilter::andFilter()
|
||||||
*/
|
*/
|
||||||
inline auto
|
inline auto
|
||||||
matchArguments (ArgSeq&& argSeq)
|
matchArguments (ArgSeq&& argSeq)
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,9 @@
|
||||||
#define TESTSUPPORT_TEST_COLL_H
|
#define TESTSUPPORT_TEST_COLL_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "lib/format-cout.hpp"
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <iostream>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
|
@ -30,20 +31,20 @@
|
||||||
namespace test {
|
namespace test {
|
||||||
|
|
||||||
|
|
||||||
typedef std::vector<int> VecI;
|
|
||||||
|
|
||||||
template<class VEC>
|
template<class VEC>
|
||||||
inline VEC
|
inline VEC
|
||||||
getTestSeq_int (const uint NUM_ELMS)
|
getTestSeq_int (const uint NUM_ELMS)
|
||||||
{
|
{
|
||||||
VEC vec;
|
VEC vec;
|
||||||
for (uint i=0; i<NUM_ELMS; ++i)
|
for (uint i=0; i<NUM_ELMS; ++i)
|
||||||
vec.push_back (i);
|
vec.emplace_back (i);
|
||||||
|
|
||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
using VecI = std::vector<int>;
|
||||||
|
|
||||||
using MapII = std::map<int,int>;
|
using MapII = std::map<int,int>;
|
||||||
using MMapII = std::multimap<int,int>;
|
using MMapII = std::multimap<int,int>;
|
||||||
|
|
||||||
|
|
@ -81,7 +82,7 @@ namespace test {
|
||||||
pullOut (ITER const& i)
|
pullOut (ITER const& i)
|
||||||
{
|
{
|
||||||
for (ITER ii(i); ii ; ++ii )
|
for (ITER ii(i); ii ; ++ii )
|
||||||
std::cout << "::" << *ii;
|
cout << "::" << *ii;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -190,19 +190,7 @@ return: 0
|
||||||
END
|
END
|
||||||
|
|
||||||
|
|
||||||
TEST "Lumiera Iterator Tools" IterTools_test 20 <<END
|
TEST "Lumiera Iterator Tools" IterTools_test <<END
|
||||||
out-lit: ::20::19::18::17::16::15::14::13::12::11::10::9::8::7::6::5::4::3::2::1
|
|
||||||
out-lit: ::20::19::18::17::16::15::14::13::12::11::10::9::8::7::6::5::4::3::2::1
|
|
||||||
out-lit: ::20::18::16::14::12::10::8::6::4::2
|
|
||||||
out-lit: ::19::17::15::13::11::9::7::5::3::1
|
|
||||||
out-lit: ::17::16::15::14::13::12::11::10::9::8::7::6::5::4::3::2::1
|
|
||||||
out-lit: ::16::14::12::10::8::6::4::2
|
|
||||||
out-lit: ::17::15::13::11::9::7::5::3::1
|
|
||||||
out-lit: ::12::18::24::30::36::42::48::54
|
|
||||||
out-lit: ::13::17::19::23::25::29::31::35::37::41::43::47::49::53::55::59
|
|
||||||
out-lit: ::20::19::18::17::16::15::14::13::12::11::10::9::8::7::6::5::4::3::2::1
|
|
||||||
out-lit: ::-20::-19::-18::-17::-16::-15::-14::-13::-12::-11::-10::-9::-8::-7::-6::-5::-4::-3::-2::-1
|
|
||||||
out-lit: ::22::21::20::19::18::17::16::15::14::13::12::11::10::9::8::7::6::5::4::3
|
|
||||||
return: 0
|
return: 0
|
||||||
END
|
END
|
||||||
|
|
||||||
|
|
@ -262,26 +250,6 @@ END
|
||||||
|
|
||||||
|
|
||||||
TEST "Iterable type detection" IterableClassification_test <<END
|
TEST "Iterable type detection" IterableClassification_test <<END
|
||||||
out: can_STL_ForEach<LongVector> : Yes
|
|
||||||
out: can_STL_ForEach<TimeSet> : Yes
|
|
||||||
out: can_STL_ForEach<CharMap> : Yes
|
|
||||||
out: can_STL_ForEach<BoolList> : Yes
|
|
||||||
out: can_STL_ForEach<ShortDeque> : Yes
|
|
||||||
out: can_STL_ForEach<CustomCont> : Yes
|
|
||||||
out: can_STL_ForEach<ForwardRangeIter> : No
|
|
||||||
out: can_STL_ForEach<TransformedForwardIter> : No
|
|
||||||
out: can_STL_ForEach<FilteredForwardIter> : No
|
|
||||||
out: can_STL_ForEach<CustomForwardIter> : No
|
|
||||||
out: can_IterForEach<LongVector> : No
|
|
||||||
out: can_IterForEach<TimeSet> : No
|
|
||||||
out: can_IterForEach<CharMap> : No
|
|
||||||
out: can_IterForEach<BoolList> : No
|
|
||||||
out: can_IterForEach<ShortDeque> : No
|
|
||||||
out: can_IterForEach<CustomCont> : No
|
|
||||||
out: can_IterForEach<ForwardRangeIter> : Yes
|
|
||||||
out: can_IterForEach<TransformedForwardIter> : Yes
|
|
||||||
out: can_IterForEach<FilteredForwardIter> : Yes
|
|
||||||
out: can_IterForEach<CustomForwardIter> : Yes
|
|
||||||
return: 0
|
return: 0
|
||||||
END
|
END
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
#include "lib/diff/mutation-message.hpp"
|
#include "lib/diff/mutation-message.hpp"
|
||||||
#include "lib/diff/tree-diff-application.hpp"
|
#include "lib/diff/tree-diff-application.hpp"
|
||||||
#include "lib/format-util.hpp"
|
#include "lib/format-util.hpp"
|
||||||
|
#include "lib/itertools.hpp"
|
||||||
#include "lib/util.hpp"
|
#include "lib/util.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
@ -47,7 +48,7 @@ namespace test{
|
||||||
string
|
string
|
||||||
contents (Rec const& object)
|
contents (Rec const& object)
|
||||||
{
|
{
|
||||||
return util::join (transformIterator (object.scope()
|
return util::join (transformIter (object.scope()
|
||||||
,[](GenNode const& n) { return n.data.get<string>(); }
|
,[](GenNode const& n) { return n.data.get<string>(); }
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,9 @@
|
||||||
|
|
||||||
|
|
||||||
using lumiera::error::Fatal;
|
using lumiera::error::Fatal;
|
||||||
using lib::transformIterator;
|
|
||||||
using lib::iter_stl::snapshot;
|
using lib::iter_stl::snapshot;
|
||||||
using lib::iter_stl::eachElm;
|
using lib::iter_stl::eachElm;
|
||||||
|
using lib::transformIter;
|
||||||
using lib::eachNum;
|
using lib::eachNum;
|
||||||
using util::_Fmt;
|
using util::_Fmt;
|
||||||
|
|
||||||
|
|
@ -215,7 +215,7 @@ namespace test {
|
||||||
"7.7--+--"
|
"7.7--+--"
|
||||||
"8.8--+--"
|
"8.8--+--"
|
||||||
"9.9"_expect);
|
"9.9"_expect);
|
||||||
CHECK (join (transformIterator(eachElm(dubious), justCount))
|
CHECK (join (transformIter (eachElm(dubious), justCount))
|
||||||
== "Nr.01(0.0), "
|
== "Nr.01(0.0), "
|
||||||
"Nr.02(2.2), "
|
"Nr.02(2.2), "
|
||||||
"Nr.03(4.4), "
|
"Nr.03(4.4), "
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ namespace test{
|
||||||
namespace { // Test fixture
|
namespace { // Test fixture
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A test »*State Core*« which steps down a number to zero.
|
* A test »**State Core**« which steps down a number to zero.
|
||||||
* @note this is a minimal description of a state progression towards a goal
|
* @note this is a minimal description of a state progression towards a goal
|
||||||
* - default constructed is equivalent to _goal was reached_
|
* - default constructed is equivalent to _goal was reached_
|
||||||
* - can be copied, manipulated and compared
|
* - can be copied, manipulated and compared
|
||||||
|
|
@ -50,7 +50,7 @@ namespace test{
|
||||||
uint n;
|
uint n;
|
||||||
|
|
||||||
StepDown (uint start =0)
|
StepDown (uint start =0)
|
||||||
: n(start)
|
: n{start}
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
||||||
|
|
@ -13,29 +13,37 @@
|
||||||
|
|
||||||
/** @file iter-explorer-test.cpp
|
/** @file iter-explorer-test.cpp
|
||||||
** The \ref IterExplorer_test covers and demonstrates a generic mechanism
|
** The \ref IterExplorer_test covers and demonstrates a generic mechanism
|
||||||
** to expand and evaluate tree like structures. It was created in response to
|
** to expand and evaluate tree like structures. This was created to address
|
||||||
** a recurring need for configurable tree expanding and backtracking evaluations.
|
** the recurring need for **tree-expanding and backtracking evaluations**.
|
||||||
** Due to the nature of Lumiera's design, we repeatedly encounter this kind of
|
** Due to the nature of Lumiera's design, we frequently encounter this type
|
||||||
** algorithms, when it comes to matching configuration and parametrisation against
|
** of evaluation pattern when it comes to matching a given configuration with
|
||||||
** a likewise hierarchical and rules based model. To keep the code base maintainable,
|
** a hierarchical and rule-based model. To keep the codebase maintainable, it
|
||||||
** we deem it crucial to reduce the inherent complexity in such algorithms by clearly
|
** is considered crucial to reduce the inherent complexity of such algorithms
|
||||||
** separate the _mechanics of evaluation_ from the actual logic of the target domain.
|
** by clearly separating the _evaluation mechanisms_ from the actual logic
|
||||||
|
** of the target domain.
|
||||||
**
|
**
|
||||||
** This test relies on a demonstration setup featuring a custom encapsulated state type:
|
** This test relies on a demonstration setup that features a **State Core** —
|
||||||
** we rely on a counter with start and end value, embedded into an iterator as »state core«.
|
** which is custom type with encapsulated evaluation state: here we rely on a
|
||||||
** This running counter, when iterated, generates a descending sequence of numbers start ... end.
|
** counter with start and end value, which however is not accessed directly from
|
||||||
** So -- conceptually -- this counting iterator can be conceived as _representing_ this sequence
|
** the outside, but rather through a set of functions expected to be present on
|
||||||
** of numbers, while not actually representing all these numbers as data in memory. And this is
|
** every »state core« (effectively this is a Concept). So this running counter,
|
||||||
** the whole point of the exercise: _not to represent_ this sequence in runtime state at once,
|
** when iterated, generates a descending sequence of numbers ∈ [start ... end[.
|
||||||
** rather to __pull and expand it on demand._
|
** So — conceptually — this counting iterator can be conceived as _representing_
|
||||||
|
** this sequence of numbers, while not actually representing all these numbers as
|
||||||
|
** data in memory. And this is the whole point of the exercise: _not to materialise_
|
||||||
|
** this sequence in runtime state at once, rather to _pull and expand it on demand_.
|
||||||
**
|
**
|
||||||
** All these tests work by first defining these _functional structures_, which just
|
** All these tests work by first defining these _functional structures_, in the form
|
||||||
** yields an iterator entity. We get the whole structure it conceptually defines
|
** of a pipeline, which, as a language construct, is embodied into an iterator entity.
|
||||||
** only if we »pull« and »materialise« this iterator until exhaustion — which essentially
|
** This is a copyable value object that implements the common function expected to be
|
||||||
** is what the test does to verify proper operation. In contrast, _Real World Code_ of course
|
** present on each »Lumiera Forward Iterator«. We then retrieve the whole structure it
|
||||||
** would not proceed in this way, like pulling everything from such an iterator. Since often
|
** conceptually defines only if we »pull« and »materialise« this iterator until it is
|
||||||
** the very reason we're using such a setup is the ability to represent infinite structures.
|
** exhausted — which essentially is what the test does to verify proper operation.
|
||||||
** Like e.g. the evaluation graph of video passed through a complex processing pipeline.
|
**
|
||||||
|
** In contrast, _Real World Code_ of course would not proceed in this way, like pulling
|
||||||
|
** everything from such an iterator. Since often the very reason we're using such a setup
|
||||||
|
** is the ability to represent infinite structures. An example would be the evaluation
|
||||||
|
** graph of video passed through a complex processing pipeline.
|
||||||
**
|
**
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -474,20 +482,20 @@ namespace test{
|
||||||
++ii;
|
++ii;
|
||||||
CHECK (3 == *ii);
|
CHECK (3 == *ii);
|
||||||
CHECK (0 == ii.depth());
|
CHECK (0 == ii.depth());
|
||||||
CHECK (materialise(ii) == "3-2-1");
|
CHECK (materialise(ii) == "3-2-1"_expect);
|
||||||
ii.expandChildren();
|
ii.expandChildren();
|
||||||
CHECK (1 == ii.depth());
|
CHECK (1 == ii.depth());
|
||||||
CHECK (materialise(ii) == "2-1-2-1");
|
CHECK (materialise(ii) == "2-1-2-1"_expect);
|
||||||
++++ii;
|
++++ii;
|
||||||
CHECK (0 == ii.depth());
|
CHECK (0 == ii.depth());
|
||||||
CHECK (materialise(ii) == "2-1");
|
CHECK (materialise(ii) == "2-1"_expect);
|
||||||
ii.expandChildren();
|
ii.expandChildren();
|
||||||
CHECK (1 == ii.depth());
|
CHECK (1 == ii.depth());
|
||||||
CHECK (materialise(ii) == "1-1");
|
CHECK (materialise(ii) == "1-1"_expect);
|
||||||
++ii;
|
++ii;
|
||||||
CHECK (0 == ii.depth());
|
CHECK (0 == ii.depth());
|
||||||
CHECK (1 == *ii);
|
CHECK (1 == *ii);
|
||||||
CHECK (materialise(ii) == "1");
|
CHECK (materialise(ii) == "1"_expect);
|
||||||
ii.expandChildren();
|
ii.expandChildren();
|
||||||
CHECK (isnil (ii));
|
CHECK (isnil (ii));
|
||||||
VERIFY_ERROR (ITER_EXHAUST, *ii );
|
VERIFY_ERROR (ITER_EXHAUST, *ii );
|
||||||
|
|
@ -586,18 +594,27 @@ namespace test{
|
||||||
// demonstrate chaining of several transformation layers
|
// demonstrate chaining of several transformation layers
|
||||||
vector<int64_t> numz{1,-2,3,-5,8,-13};
|
vector<int64_t> numz{1,-2,3,-5,8,-13};
|
||||||
|
|
||||||
CHECK ("≺1≻-≺-2≻-≺3≻-≺-5≻-≺8≻-≺-13≻" == materialise (explore(numz)
|
CHECK (materialise (
|
||||||
.transform(formatify)) );
|
explore(numz)
|
||||||
|
.transform(formatify)
|
||||||
|
)
|
||||||
|
== "≺1≻-≺-2≻-≺3≻-≺-5≻-≺8≻-≺-13≻"_expect);
|
||||||
|
|
||||||
CHECK ("≺2≻-≺-4≻-≺6≻-≺-10≻-≺16≻-≺-26≻" == materialise (explore(numz)
|
CHECK (materialise (
|
||||||
|
explore(numz)
|
||||||
.transform(multiply)
|
.transform(multiply)
|
||||||
.transform(formatify)) );
|
.transform(formatify)
|
||||||
|
)
|
||||||
|
== "≺2≻-≺-4≻-≺6≻-≺-10≻-≺16≻-≺-26≻"_expect);
|
||||||
|
|
||||||
CHECK ("≺≺4≻≻-≺≺-8≻≻-≺≺12≻≻-≺≺-20≻≻-≺≺32≻≻-≺≺-52≻≻" == materialise (explore(numz)
|
CHECK (materialise (
|
||||||
|
explore(numz)
|
||||||
.transform(multiply)
|
.transform(multiply)
|
||||||
.transform(multiply)
|
.transform(multiply)
|
||||||
.transform(formatify)
|
.transform(formatify)
|
||||||
.transform(formatify)) );
|
.transform(formatify)
|
||||||
|
)
|
||||||
|
== "≺≺4≻≻-≺≺-8≻≻-≺≺12≻≻-≺≺-20≻≻-≺≺32≻≻-≺≺-52≻≻"_expect);
|
||||||
|
|
||||||
|
|
||||||
// demonstrate the functor is evaluated only once per step
|
// demonstrate the functor is evaluated only once per step
|
||||||
|
|
@ -869,8 +886,8 @@ namespace test{
|
||||||
CHECK (materialise (
|
CHECK (materialise (
|
||||||
explore(CountDown{10})
|
explore(CountDown{10})
|
||||||
.transform(util::toString<uint>)
|
.transform(util::toString<uint>)
|
||||||
.groupedBy([](auto& it) { return std::ilogbf (it.p); }) // note trickery: takes not the value, rather the iterator and
|
.groupedBy([](auto& it) { return std::ilogbf (it.p); }) // note trickery: accept not the value, rather the iterator and
|
||||||
) // accesses internals of CountDown, bypassing the transform layer above
|
) // access internals of CountDown, bypassing the transform layer above
|
||||||
== "1098-7654-32-1"_expect); // `+` does string concatenation
|
== "1098-7654-32-1"_expect); // `+` does string concatenation
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1577,8 +1594,8 @@ namespace test{
|
||||||
{
|
{
|
||||||
uint val = get<0>(tup);
|
uint val = get<0>(tup);
|
||||||
uint sum = get<1>(tup);
|
uint sum = get<1>(tup);
|
||||||
return val? singleValIterator (Tu2{val-1, sum+val})
|
return val? singletonIter(Tu2{val-1, sum+val})
|
||||||
: SingleValIter<Tu2>();
|
: nilIter<Tu2>();
|
||||||
};
|
};
|
||||||
|
|
||||||
CHECK (materialise(
|
CHECK (materialise(
|
||||||
|
|
|
||||||
|
|
@ -310,7 +310,7 @@ namespace test{
|
||||||
|
|
||||||
template<class MAP>
|
template<class MAP>
|
||||||
void
|
void
|
||||||
verify_MultimapIters() ///< @see IterTools_test#verify_filterRepetitions
|
verify_MultimapIters() ///< @see IterTools_test#verify_filterRepeat
|
||||||
{
|
{
|
||||||
MAP testMap;
|
MAP testMap;
|
||||||
for (uint i=0; i<NUM_ELMS; ++i)
|
for (uint i=0; i<NUM_ELMS; ++i)
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
IterTools(Test) - building combined and filtering iterators based on the Iterator tools
|
IterTools(Test) - building combined and filtering iterators based on the Iterator tools
|
||||||
|
|
||||||
Copyright (C)
|
Copyright (C)
|
||||||
2009, Hermann Vosseler <Ichthyostega@web.de>
|
2009,2026 Hermann Vosseler <Ichthyostega@web.de>
|
||||||
|
|
||||||
**Lumiera** is free software; you can redistribute it and/or modify it
|
**Lumiera** is free software; you can redistribute it and/or modify it
|
||||||
under the terms of the GNU General Public License as published by the
|
under the terms of the GNU General Public License as published by the
|
||||||
|
|
@ -16,53 +16,41 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "test/run.hpp"
|
#include "test/run.hpp"
|
||||||
|
#include "lib/itertools.hpp"
|
||||||
|
#include "test/test-coll.hpp"
|
||||||
#include "test/test-helper.hpp"
|
#include "test/test-helper.hpp"
|
||||||
#include "lib/util-foreach.hpp"
|
#include "lib/iter-adapter-stl.hpp"
|
||||||
#include "lib/format-cout.hpp"
|
#include "lib/format-util.hpp"
|
||||||
#include "lib/util.hpp"
|
#include "lib/util.hpp"
|
||||||
|
|
||||||
#include "lib/itertools.hpp"
|
|
||||||
|
|
||||||
#include <boost/lexical_cast.hpp>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
|
using test::Test;
|
||||||
|
using util::isnil;
|
||||||
|
using util::join;
|
||||||
|
|
||||||
|
using std::vector;
|
||||||
|
using test::VecI;
|
||||||
|
using test::getTestSeq_int;
|
||||||
|
using test::showType;
|
||||||
|
|
||||||
namespace lib {
|
namespace lib {
|
||||||
namespace test{
|
namespace test{
|
||||||
|
|
||||||
using ::Test;
|
|
||||||
using boost::lexical_cast;
|
|
||||||
using util::for_each;
|
|
||||||
using util::isnil;
|
|
||||||
using std::vector;
|
|
||||||
|
|
||||||
using LERR_(ITER_EXHAUST);
|
using LERR_(ITER_EXHAUST);
|
||||||
|
|
||||||
|
|
||||||
|
namespace { // a test iterator
|
||||||
|
|
||||||
namespace { // Test data
|
const uint NUM_ELMS{10};
|
||||||
|
const auto TEST_NUMZ = getTestSeq_int<VecI> (NUM_ELMS);
|
||||||
|
|
||||||
struct TestSource
|
inline auto
|
||||||
|
iterNum()
|
||||||
{
|
{
|
||||||
vector<int> data_;
|
return RangeIter{TEST_NUMZ.begin(), TEST_NUMZ.end()};
|
||||||
|
|
||||||
TestSource(uint num)
|
|
||||||
{
|
|
||||||
while (num)
|
|
||||||
data_.push_back(num--);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef vector<int>::iterator sourceIter;
|
|
||||||
typedef RangeIter<sourceIter> iterator;
|
|
||||||
|
|
||||||
iterator begin() { return iterator(data_.begin(),data_.end()); }
|
|
||||||
iterator end() { return iterator(); }
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} // (END) Test data
|
} // (END) Test data
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -72,266 +60,55 @@ namespace test{
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************//**
|
/***************************************************************************//**
|
||||||
* @test build combined and filtering iterators with the help of lib::IterTool.
|
* @test build simple filter and transforming iterators using the »itertools«.
|
||||||
* Check correct behaviour of the resulting iterators and
|
* Check correct behaviour of the resulting iterators and
|
||||||
* verify they fulfil the Lumiera Forward Iterator concept
|
* verify they behave like a **Lumiera Forward Iterator**.
|
||||||
*
|
|
||||||
* @todo implement more iterator tools.... see Ticket #347
|
|
||||||
*/
|
*/
|
||||||
class IterTools_test : public Test
|
class IterTools_test : public Test
|
||||||
{
|
{
|
||||||
|
|
||||||
typedef TestSource::iterator Iter;
|
using Iter = decltype(iterNum());
|
||||||
|
|
||||||
uint NUM_ELMS{0};
|
|
||||||
|
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
run (Arg arg)
|
run (Arg)
|
||||||
{
|
{
|
||||||
NUM_ELMS = firstVal (arg, 10);
|
verify_testSetup();
|
||||||
|
|
||||||
TestSource source(NUM_ELMS);
|
verify_singleIter();
|
||||||
|
verify_filterIter();
|
||||||
pullOut (source.begin());
|
verify_filterRepeat();
|
||||||
verifyComparisons (source.begin());
|
verify_transformIter();
|
||||||
|
verify_pullLast();
|
||||||
|
|
||||||
buildFilterIterator (source.begin());
|
|
||||||
Iter ii (source.begin());
|
|
||||||
++++++ii;
|
|
||||||
buildFilterIterator (ii);
|
|
||||||
verify_filterExtension();
|
|
||||||
verify_filterRepetitions();
|
|
||||||
|
|
||||||
buildWrappedSingleElement();
|
|
||||||
|
|
||||||
buildTransformingIterator (source.begin());
|
|
||||||
|
|
||||||
verifyPullLast(source.begin());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** @test fundamental iterator behaviour. */
|
||||||
template<class IT>
|
|
||||||
void
|
void
|
||||||
pullOut (IT const& ii)
|
verify_testSetup()
|
||||||
{
|
{
|
||||||
for (IT iter(ii) ; iter; ++iter )
|
Iter ii = iterNum();
|
||||||
cout << "::" << *iter;
|
|
||||||
cout << endl;
|
CHECK (ii);
|
||||||
|
CHECK (not isnil(ii));
|
||||||
|
CHECK (0 == *ii);
|
||||||
|
++++ii;
|
||||||
|
CHECK (2 == *ii);
|
||||||
|
|
||||||
|
verifyComparisons(ii);
|
||||||
|
CHECK (join (ii) == "2, 3, 4, 5, 6, 7, 8, 9"_expect );
|
||||||
|
CHECK (join (ii, "-") == "2-3-4-5-6-7-8-9"_expect );
|
||||||
|
CHECK (ii);
|
||||||
|
CHECK (2 == *ii);
|
||||||
|
|
||||||
|
while (ii)
|
||||||
|
++ii;
|
||||||
|
CHECK (not ii);
|
||||||
|
VERIFY_ERROR (ITER_EXHAUST, *ii );
|
||||||
|
VERIFY_ERROR (ITER_EXHAUST, ++ii);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static bool takeAll (int) { return true; }
|
|
||||||
static bool takeOdd (int i) { return 0 != i % 2; }
|
|
||||||
static bool takeEve (int i) { return 0 == i % 2; }
|
|
||||||
static bool takeTrd (int i) { return 0 == i % 3; }
|
|
||||||
|
|
||||||
void
|
|
||||||
buildFilterIterator (Iter const& ii)
|
|
||||||
{
|
|
||||||
pullOut (filterIterator (ii, takeAll)); // note: using the convenient builder function
|
|
||||||
pullOut (filterIterator (ii, takeEve));
|
|
||||||
pullOut (filterIterator (ii, takeOdd));
|
|
||||||
|
|
||||||
FilterIter<Iter> all (ii, takeAll);
|
|
||||||
FilterIter<Iter> odd (ii, takeOdd);
|
|
||||||
verifyComparisons (all);
|
|
||||||
verifyComparisons (odd);
|
|
||||||
|
|
||||||
while (++all && ++odd)
|
|
||||||
CHECK (all != odd);
|
|
||||||
|
|
||||||
while (++all) { }
|
|
||||||
CHECK (isnil (odd));
|
|
||||||
CHECK (all == odd);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** @test verify the ability to extend a filter condition
|
|
||||||
* while in the middle of an ongoing iteration.
|
|
||||||
* Typically this means sharpening the filter condition
|
|
||||||
* and thus making the filter more restrictive, filtering
|
|
||||||
* away more elements of the source stream. But through
|
|
||||||
* the ability to add disjunctive and negated clauses,
|
|
||||||
* it is also possible to weaken the filter condition
|
|
||||||
* @note in case of a weakened filter condition, there is
|
|
||||||
* \em no reset of the source iterator, i.e. we don't
|
|
||||||
* re-evaluate from start, but just from current head.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
verify_filterExtension ()
|
|
||||||
{
|
|
||||||
typedef vector<uint64_t> Src;
|
|
||||||
typedef Src::iterator SrcIter;
|
|
||||||
typedef RangeIter<SrcIter> SeqIter;
|
|
||||||
typedef ExtensibleFilterIter<SeqIter> FilteredSeq;
|
|
||||||
|
|
||||||
Src src;
|
|
||||||
for (uint i=0; i < 3*NUM_ELMS; ++i)
|
|
||||||
src.push_back(i);
|
|
||||||
|
|
||||||
SeqIter completeSequence (src.begin(), src.end());
|
|
||||||
FilteredSeq filterIter (completeSequence, takeAll);
|
|
||||||
|
|
||||||
CHECK (!isnil (filterIter));
|
|
||||||
CHECK (0 == *filterIter);
|
|
||||||
++filterIter;
|
|
||||||
CHECK (1 == *filterIter);
|
|
||||||
|
|
||||||
filterIter.andFilter(takeEve);
|
|
||||||
CHECK (!isnil (filterIter));
|
|
||||||
CHECK (2 == *filterIter);
|
|
||||||
++filterIter;
|
|
||||||
CHECK (4 == *filterIter);
|
|
||||||
|
|
||||||
// sharpen the condition...
|
|
||||||
filterIter.andFilter(takeTrd);
|
|
||||||
CHECK (!isnil (filterIter));
|
|
||||||
CHECK (6 == *filterIter); // divisible by two and by three
|
|
||||||
++filterIter;
|
|
||||||
CHECK (12 == *filterIter);
|
|
||||||
|
|
||||||
verifyComparisons (filterIter);
|
|
||||||
pullOut (filterIter);
|
|
||||||
|
|
||||||
// adding a disjunctive clause actually weakens the filter...
|
|
||||||
filterIter = {completeSequence, takeTrd};
|
|
||||||
CHECK (!isnil (filterIter));
|
|
||||||
CHECK (0 == *filterIter);
|
|
||||||
++filterIter;
|
|
||||||
CHECK (3 == *filterIter);
|
|
||||||
|
|
||||||
filterIter.orFilter(takeEve);
|
|
||||||
CHECK (3 == *filterIter);
|
|
||||||
++filterIter;
|
|
||||||
CHECK (4 == *filterIter);
|
|
||||||
++filterIter;
|
|
||||||
CHECK (6 == *filterIter);
|
|
||||||
verifyComparisons (filterIter);
|
|
||||||
|
|
||||||
// flip filter logic
|
|
||||||
filterIter.flipFilter();
|
|
||||||
CHECK (7 == *filterIter); // not even and not divisible by three
|
|
||||||
++filterIter;
|
|
||||||
CHECK (11 == *filterIter);
|
|
||||||
++filterIter;
|
|
||||||
CHECK (13 == *filterIter);
|
|
||||||
|
|
||||||
verifyComparisons (filterIter);
|
|
||||||
pullOut (filterIter);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** @test verify the helper to filter duplicate elements
|
|
||||||
* emitted by an source iterator. This test creates
|
|
||||||
* a sequence of numbers with random repetitions.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
verify_filterRepetitions ()
|
|
||||||
{
|
|
||||||
vector<uint> numberz;
|
|
||||||
for (uint i=0; i<NUM_ELMS; ++i)
|
|
||||||
{
|
|
||||||
uint n = 1 + rani (100);
|
|
||||||
do numberz.push_back(i);
|
|
||||||
while (--n);
|
|
||||||
}
|
|
||||||
CHECK (NUM_ELMS < numberz.size(), "no repetition in test data??");
|
|
||||||
|
|
||||||
typedef vector<uint>::iterator SrcIter;
|
|
||||||
typedef RangeIter<SrcIter> SeqIter;
|
|
||||||
typedef FilterIter<SeqIter> FilteredSeq;
|
|
||||||
|
|
||||||
SeqIter completeSequence (numberz.begin(), numberz.end());
|
|
||||||
FilteredSeq filtered = filterRepetitions (completeSequence);
|
|
||||||
|
|
||||||
uint num=0;
|
|
||||||
for (; num<NUM_ELMS and not isnil(filtered);
|
|
||||||
++num,
|
|
||||||
++filtered
|
|
||||||
)
|
|
||||||
CHECK (num == *filtered);
|
|
||||||
|
|
||||||
CHECK (num == NUM_ELMS and isnil(filtered));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** @test wrap an arbitrary single element as pseudo-iterator */
|
|
||||||
void
|
|
||||||
buildWrappedSingleElement()
|
|
||||||
{
|
|
||||||
uint i{12};
|
|
||||||
|
|
||||||
auto i1 = singleValIterator(12);
|
|
||||||
auto i2 = singleValIterator( i);
|
|
||||||
auto i3 = singleValIterator(&i);
|
|
||||||
|
|
||||||
CHECK (not isnil(i1));
|
|
||||||
CHECK (not isnil(i2));
|
|
||||||
CHECK (not isnil(i3));
|
|
||||||
CHECK (12 == *i1);
|
|
||||||
CHECK (12 == *i2);
|
|
||||||
CHECK (12 == **i3);
|
|
||||||
|
|
||||||
i = 23;
|
|
||||||
CHECK (12 == *i1);
|
|
||||||
CHECK (23 == *i2);
|
|
||||||
CHECK (23 == **i3);
|
|
||||||
|
|
||||||
++i1;
|
|
||||||
++i2;
|
|
||||||
++i3;
|
|
||||||
CHECK (isnil(i1));
|
|
||||||
CHECK (isnil(i2));
|
|
||||||
CHECK (isnil(i3));
|
|
||||||
VERIFY_ERROR (ITER_EXHAUST, *i1 );
|
|
||||||
VERIFY_ERROR (ITER_EXHAUST, *i2 );
|
|
||||||
VERIFY_ERROR (ITER_EXHAUST, *i3 );
|
|
||||||
|
|
||||||
// assignable as any iterator..
|
|
||||||
i1 = singleValIterator(13);
|
|
||||||
CHECK (13 == *i1);
|
|
||||||
|
|
||||||
i1 = SingleValIter<int>{};
|
|
||||||
CHECK (isnil(i1));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static ulong addTwo (int i) { return i+2; }
|
|
||||||
static int negate (int i) { return -i; }
|
|
||||||
static int idFunc (int i) { return i; }
|
|
||||||
|
|
||||||
void
|
|
||||||
buildTransformingIterator (Iter const& ii)
|
|
||||||
{
|
|
||||||
pullOut (transformIterator(ii, idFunc));
|
|
||||||
pullOut (transformIterator(ii, negate));
|
|
||||||
pullOut (transformIterator(ii, addTwo)); // note: changing output type to unsigned
|
|
||||||
|
|
||||||
TransformIter<Iter, int> idi (ii, idFunc);
|
|
||||||
TransformIter<Iter, int> neg (ii, negate);
|
|
||||||
verifyComparisons (idi);
|
|
||||||
verifyComparisons (neg);
|
|
||||||
|
|
||||||
CHECK (idi);
|
|
||||||
CHECK (neg);
|
|
||||||
for ( ;idi&&neg;
|
|
||||||
++idi,++neg)
|
|
||||||
CHECK (idi != neg);
|
|
||||||
|
|
||||||
CHECK (!idi and !neg);
|
|
||||||
CHECK (idi == neg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** @test verify equality handling and NIL detection
|
/** @test verify equality handling and NIL detection
|
||||||
* for the given iterator/wrapper handed in */
|
* for the given iterator/wrapper handed in */
|
||||||
template<class IT>
|
template<class IT>
|
||||||
|
|
@ -370,11 +147,159 @@ namespace test{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** @test wrap an arbitrary single element as pseudo-iterator */
|
||||||
void
|
void
|
||||||
verifyPullLast(Iter const& ii)
|
verify_singleIter()
|
||||||
{
|
{
|
||||||
|
uint i{12};
|
||||||
|
|
||||||
|
auto i1 = singletonIter (12);
|
||||||
|
auto i2 = singletonIter ( i);
|
||||||
|
auto i3 = singletonIter (&i);
|
||||||
|
|
||||||
|
CHECK (not isnil(i1));
|
||||||
|
CHECK (not isnil(i2));
|
||||||
|
CHECK (not isnil(i3));
|
||||||
|
CHECK (12 == *i1);
|
||||||
|
CHECK (12 == *i2);
|
||||||
|
CHECK (12 == **i3);
|
||||||
|
|
||||||
|
i = 23;
|
||||||
|
CHECK (12 == *i1);
|
||||||
|
CHECK (23 == *i2);
|
||||||
|
CHECK (23 == **i3);
|
||||||
|
|
||||||
|
++i1;
|
||||||
|
++i2;
|
||||||
|
++i3;
|
||||||
|
CHECK (isnil(i1));
|
||||||
|
CHECK (isnil(i2));
|
||||||
|
CHECK (isnil(i3));
|
||||||
|
VERIFY_ERROR (ITER_EXHAUST, *i1 );
|
||||||
|
VERIFY_ERROR (ITER_EXHAUST, *i2 );
|
||||||
|
VERIFY_ERROR (ITER_EXHAUST, *i3 );
|
||||||
|
|
||||||
|
// assignable as any iterator...
|
||||||
|
auto i0 = nilIter<int>();
|
||||||
|
i0 = singletonIter (13);
|
||||||
|
CHECK (13 == *i0);
|
||||||
|
CHECK (isnil (i1));
|
||||||
|
std::swap (i0,i1);
|
||||||
|
CHECK (isnil (i0));
|
||||||
|
CHECK (13 == *i1);
|
||||||
|
|
||||||
|
i1 = iter::Single<int>{};
|
||||||
|
CHECK (isnil(i1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool takeAll (int) { return true; }
|
||||||
|
static bool takeOdd (int i) { return 0 != i % 2; }
|
||||||
|
static bool takeEve (int i) { return 0 == i % 2; }
|
||||||
|
static bool takeTrd (int i) { return 0 == i % 3; }
|
||||||
|
|
||||||
|
/** @test build a filter pipeline based on a predicate */
|
||||||
|
void
|
||||||
|
verify_filterIter()
|
||||||
|
{
|
||||||
|
Iter ii = iterNum();
|
||||||
|
|
||||||
|
CHECK (join (filterIter (ii, takeAll)) == "0, 1, 2, 3, 4, 5, 6, 7, 8, 9"_expect );
|
||||||
|
CHECK (join (filterIter (ii, takeEve)) == "0, 2, 4, 6, 8"_expect );
|
||||||
|
CHECK (join (filterIter (ii, takeOdd)) == "1, 3, 5, 7, 9"_expect );
|
||||||
|
|
||||||
|
auto all = filterIter (ii, takeAll);
|
||||||
|
auto odd = filterIter (ii, takeOdd);
|
||||||
|
verifyComparisons (all);
|
||||||
|
verifyComparisons (odd);
|
||||||
|
|
||||||
|
while (++all and ++odd)
|
||||||
|
CHECK (all != odd);
|
||||||
|
|
||||||
|
while (++all) { }
|
||||||
|
CHECK (isnil (odd));
|
||||||
|
CHECK (all == odd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** @test verify the helper to filter duplicate elements
|
||||||
|
* emitted by an source iterator. This test creates
|
||||||
|
* a sequence of numbers with random repetitions.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
verify_filterRepeat()
|
||||||
|
{
|
||||||
|
vector<uint> numberz;
|
||||||
|
for (uint i=0; i<NUM_ELMS; ++i)
|
||||||
|
{
|
||||||
|
uint n = 1 + rani (100);
|
||||||
|
do numberz.push_back(i);
|
||||||
|
while (--n);
|
||||||
|
}
|
||||||
|
CHECK (NUM_ELMS < numberz.size(), "no repetition in test data??");
|
||||||
|
|
||||||
|
auto completeSequence = iter_stl::eachElm (numberz);
|
||||||
|
auto filtered = filterRepeat (completeSequence);
|
||||||
|
|
||||||
|
uint num=0;
|
||||||
|
for (; num < NUM_ELMS and not isnil(filtered);
|
||||||
|
++num,
|
||||||
|
++filtered
|
||||||
|
)
|
||||||
|
CHECK (num == *filtered);
|
||||||
|
|
||||||
|
CHECK (num == NUM_ELMS and isnil(filtered));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static uint addTwo (int i) { return i+2; }
|
||||||
|
static int negate (int i) { return -i; }
|
||||||
|
static int idFunc (int i) { return i; }
|
||||||
|
|
||||||
|
/** @test build a pipeline that maps a function onto the iterator results */
|
||||||
|
void
|
||||||
|
verify_transformIter()
|
||||||
|
{
|
||||||
|
Iter ii = iterNum();
|
||||||
|
|
||||||
|
CHECK (join (transformIter (ii, idFunc)) == "0, 1, 2, 3, 4, 5, 6, 7, 8, 9"_expect );
|
||||||
|
CHECK (join (transformIter (ii, negate)) == "0, -1, -2, -3, -4, -5, -6, -7, -8, -9"_expect );
|
||||||
|
CHECK (join (transformIter (ii, addTwo)) == "2, 3, 4, 5, 6, 7, 8, 9, 10, 11"_expect );
|
||||||
|
|
||||||
|
// note: output type changed to unsigned
|
||||||
|
using TransIT = decltype(transformIter (ii, addTwo));
|
||||||
|
CHECK (showType<TransIT::value_type>() == "uint"_expect);
|
||||||
|
|
||||||
|
auto idi = transformIter (ii, idFunc);
|
||||||
|
auto neg = transformIter (ii, negate);
|
||||||
|
verifyComparisons (idi);
|
||||||
|
verifyComparisons (neg);
|
||||||
|
|
||||||
|
CHECK (idi == neg); // Note twist: same type, different functor, yet same result (≡0)
|
||||||
|
CHECK (++idi);
|
||||||
|
CHECK (++neg);
|
||||||
|
for ( ; idi and neg;
|
||||||
|
++idi,
|
||||||
|
++neg)
|
||||||
|
{
|
||||||
|
CHECK ( idi != neg);
|
||||||
|
CHECK (*idi != *neg);
|
||||||
|
}
|
||||||
|
|
||||||
|
CHECK (!idi and !neg);
|
||||||
|
CHECK (idi == neg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** @test helper to pull an iterator until its last element */
|
||||||
|
void
|
||||||
|
verify_pullLast()
|
||||||
|
{
|
||||||
|
Iter ii = iterNum();
|
||||||
Iter::value_type lastElm = pull_last (ii);
|
Iter::value_type lastElm = pull_last (ii);
|
||||||
CHECK (1 == lastElm); // TestSource holds a decreasing sequence of numbers ending with 1
|
CHECK (NUM_ELMS-1 == lastElm);
|
||||||
|
|
||||||
Iter emptyIterator;
|
Iter emptyIterator;
|
||||||
CHECK (isnil (emptyIterator));
|
CHECK (isnil (emptyIterator));
|
||||||
|
|
@ -387,4 +312,3 @@ namespace test{
|
||||||
|
|
||||||
|
|
||||||
}} // namespace lib::test
|
}} // namespace lib::test
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,16 +13,17 @@
|
||||||
|
|
||||||
/** @file iterable-classification-test.cpp
|
/** @file iterable-classification-test.cpp
|
||||||
** unit test \ref IterableClassification_test
|
** unit test \ref IterableClassification_test
|
||||||
|
** @see iter-adapter.hpp
|
||||||
|
** @see lib/meta/trait.hpp
|
||||||
|
** @see lib/meta/duck-detector.hpp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "test/run.hpp"
|
#include "test/run.hpp"
|
||||||
|
|
||||||
#include "steam/mobject/session/scope-query.hpp"
|
#include "lib/meta/trait.hpp"
|
||||||
#include "steam/mobject/session/effect.hpp"
|
#include "lib/diff/record.hpp"
|
||||||
#include "lib/meta/duck-detector.hpp"
|
|
||||||
#include "lib/time/timevalue.hpp"
|
#include "lib/time/timevalue.hpp"
|
||||||
#include "lib/util-foreach.hpp"
|
|
||||||
#include "lib/itertools.hpp"
|
#include "lib/itertools.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
@ -33,51 +34,60 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::vector;
|
||||||
|
using std::declval;
|
||||||
|
using lib::time::TimeVar;
|
||||||
|
|
||||||
namespace lib {
|
namespace lib {
|
||||||
namespace meta {
|
namespace meta {
|
||||||
namespace test {
|
namespace test {
|
||||||
|
|
||||||
using steam::mobject::session::Effect;
|
|
||||||
using steam::mobject::session::ScopeQuery;
|
|
||||||
typedef lib::time::TimeVar Time;
|
|
||||||
|
|
||||||
using std::cout;
|
|
||||||
using std::endl;
|
|
||||||
|
|
||||||
|
|
||||||
namespace { // a custom test container....
|
namespace { // a custom test container....
|
||||||
|
|
||||||
|
/// @note: a bare type definition is sufficient here....
|
||||||
struct TestSource
|
struct TestSource
|
||||||
{
|
{
|
||||||
vector<int> data_;
|
|
||||||
|
|
||||||
TestSource(uint num);
|
TestSource(uint num);
|
||||||
|
|
||||||
typedef vector<int>::iterator sourceIter;
|
using RawIter = vector<int>::iterator;
|
||||||
typedef RangeIter<sourceIter> iterator;
|
using iterator = RangeIter<RawIter>;
|
||||||
|
|
||||||
iterator begin() ;
|
iterator begin() ;
|
||||||
iterator end() ;
|
iterator end() ;
|
||||||
// note: a bare type definition is sufficient here....
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline auto transformedSource(TestSource& src){ return lib::transformIter (src.begin(), [](int){ return long(0); }); }
|
||||||
|
inline auto filteredSource (TestSource& src){ return lib::filterIter (src.begin(), [](int){ return true; }); }
|
||||||
|
|
||||||
|
|
||||||
|
/// @note Dummy type that exposes a »*State Core*« interface.
|
||||||
|
struct DummyCore
|
||||||
|
{
|
||||||
|
bool checkPoint() const;
|
||||||
|
uint& yield() const;
|
||||||
|
void iterNext();
|
||||||
|
friend bool operator== (DummyCore const&, DummyCore const&);
|
||||||
|
};
|
||||||
|
|
||||||
}//(End) test containers
|
}//(End) test containers
|
||||||
|
|
||||||
#define SHOW_CHECK(_EXPR_) cout << STRINGIFY(_EXPR_) << "\t : " << (_EXPR_::value? "Yes":"No") << endl;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************//**
|
/*******************************************************************************//**
|
||||||
* @test verify the (static) classification/detection of iterables.
|
* @test verify the (static) classification/detection of iterables.
|
||||||
* Currently (1/10) we're able to detect the following
|
* Using some SFINAE trickery, it is possible to detect the following
|
||||||
* - a STL like container with \c begin() and \c end()
|
* - a _STL-like container_ with `begin()` and `end()`
|
||||||
* - a Lumiera Forward Iterator
|
* - a _Lumiera Forward Iterator_
|
||||||
* This test just retrieves the results of a compile time execution
|
* - a _State Core_
|
||||||
* of the type detection; thus we just define types and then access
|
* This test ensures this compile time detection works as intended;
|
||||||
|
* it suffices thus to define some minimal types in order to access
|
||||||
* the generated meta function value.
|
* the generated meta function value.
|
||||||
|
* @see iter-adapter.hpp explanation of _Lumiera Forward Iterator_ and _State Core_
|
||||||
|
* @todo 2026 many years later and this type detection has become a cornerstone
|
||||||
|
* of Lumiera's iterator pipeline framework. Since the language level has
|
||||||
|
* been raised recently to C++23, it should be considered to replace
|
||||||
|
* the SFINAE-based traits with Concept definitions.
|
||||||
*/
|
*/
|
||||||
class IterableClassification_test : public Test
|
class IterableClassification_test : public Test
|
||||||
{
|
{
|
||||||
|
|
@ -86,45 +96,71 @@ namespace test {
|
||||||
run (Arg)
|
run (Arg)
|
||||||
{
|
{
|
||||||
// define a bunch of STL containers
|
// define a bunch of STL containers
|
||||||
typedef std::vector<long> LongVector;
|
using TimeVector = std::vector<TimeVar>;
|
||||||
typedef std::multiset<Time> TimeSet;
|
using LongSet = std::multiset<long> ;
|
||||||
typedef std::map<int,char> CharMap;
|
using CharMap = std::map<int,char> ;
|
||||||
typedef std::list<bool> BoolList;
|
using BoolList = std::list<bool> ;
|
||||||
typedef std::deque<ushort> ShortDeque;
|
using ShortDeque = std::deque<ushort> ;
|
||||||
typedef TestSource CustomCont;
|
using CustomCont = TestSource ;
|
||||||
|
|
||||||
// some types in compliance to the "Lumiera Forward Iterator" concept
|
// some types that comply with the "Lumiera Forward Iterator" concept
|
||||||
typedef TestSource::iterator ForwardRangeIter;
|
using LumieraRangeIter = TestSource::iterator;
|
||||||
typedef TransformIter<ForwardRangeIter, long> TransformedForwardIter;
|
using LumieraFilteredIter = decltype( filteredSource (declval<TestSource&>()) );
|
||||||
typedef FilterIter<TransformedForwardIter> FilteredForwardIter;
|
using LumieraTransformedIter = decltype( transformedSource (declval<TestSource&>()) );
|
||||||
typedef ScopeQuery<Effect>::iterator CustomForwardIter;
|
using CustomLumieraIter = diff::Record<string>::iterator;
|
||||||
|
|
||||||
|
// some types that comply with the "State Core" concept
|
||||||
|
using CustomStateCore = DummyCore;
|
||||||
|
using LumieraCoreIter = IterableDecorator<DummyCore>;
|
||||||
|
|
||||||
|
|
||||||
// detect STL iteration
|
// detect STL iteration
|
||||||
SHOW_CHECK( can_STL_ForEach<LongVector> );
|
CHECK ( true == can_STL_ForEach<TimeVector>::value );
|
||||||
SHOW_CHECK( can_STL_ForEach<TimeSet> );
|
CHECK ( true == can_STL_ForEach<LongSet> ::value );
|
||||||
SHOW_CHECK( can_STL_ForEach<CharMap> );
|
CHECK ( true == can_STL_ForEach<CharMap> ::value );
|
||||||
SHOW_CHECK( can_STL_ForEach<BoolList> );
|
CHECK ( true == can_STL_ForEach<BoolList> ::value );
|
||||||
SHOW_CHECK( can_STL_ForEach<ShortDeque> );
|
CHECK ( true == can_STL_ForEach<ShortDeque>::value );
|
||||||
SHOW_CHECK( can_STL_ForEach<CustomCont> );
|
CHECK ( true == can_STL_ForEach<CustomCont>::value );
|
||||||
|
|
||||||
SHOW_CHECK( can_STL_ForEach<ForwardRangeIter> );
|
CHECK (false == can_STL_ForEach<LumieraRangeIter> ::value );
|
||||||
SHOW_CHECK( can_STL_ForEach<TransformedForwardIter> );
|
CHECK (false == can_STL_ForEach<LumieraFilteredIter> ::value );
|
||||||
SHOW_CHECK( can_STL_ForEach<FilteredForwardIter> );
|
CHECK (false == can_STL_ForEach<LumieraTransformedIter>::value );
|
||||||
SHOW_CHECK( can_STL_ForEach<CustomForwardIter> );
|
CHECK (false == can_STL_ForEach<CustomLumieraIter> ::value );
|
||||||
|
|
||||||
|
CHECK (false == can_STL_ForEach<CustomStateCore>::value );
|
||||||
|
CHECK (false == can_STL_ForEach<LumieraCoreIter>::value );
|
||||||
|
|
||||||
// detect Lumiera Forward Iterator
|
// detect Lumiera Forward Iterator
|
||||||
SHOW_CHECK( can_IterForEach<LongVector> );
|
CHECK (false == can_IterForEach<TimeVector>::value );
|
||||||
SHOW_CHECK( can_IterForEach<TimeSet> );
|
CHECK (false == can_IterForEach<LongSet> ::value );
|
||||||
SHOW_CHECK( can_IterForEach<CharMap> );
|
CHECK (false == can_IterForEach<CharMap> ::value );
|
||||||
SHOW_CHECK( can_IterForEach<BoolList> );
|
CHECK (false == can_IterForEach<BoolList> ::value );
|
||||||
SHOW_CHECK( can_IterForEach<ShortDeque> );
|
CHECK (false == can_IterForEach<ShortDeque>::value );
|
||||||
SHOW_CHECK( can_IterForEach<CustomCont> );
|
CHECK (false == can_IterForEach<CustomCont>::value );
|
||||||
|
|
||||||
SHOW_CHECK( can_IterForEach<ForwardRangeIter> );
|
CHECK ( true == can_IterForEach<LumieraRangeIter> ::value );
|
||||||
SHOW_CHECK( can_IterForEach<TransformedForwardIter> );
|
CHECK ( true == can_IterForEach<LumieraFilteredIter> ::value );
|
||||||
SHOW_CHECK( can_IterForEach<FilteredForwardIter> );
|
CHECK ( true == can_IterForEach<LumieraTransformedIter>::value );
|
||||||
SHOW_CHECK( can_IterForEach<CustomForwardIter> );
|
CHECK ( true == can_IterForEach<CustomLumieraIter> ::value );
|
||||||
|
|
||||||
|
CHECK (false == can_IterForEach<CustomStateCore>::value );
|
||||||
|
CHECK ( true == can_IterForEach<LumieraCoreIter>::value ); // Note: Lumiera iterator capability added as wrapper
|
||||||
|
|
||||||
|
// detect State Core
|
||||||
|
CHECK (false == is_StateCore<TimeVector>::value );
|
||||||
|
CHECK (false == is_StateCore<LongSet> ::value );
|
||||||
|
CHECK (false == is_StateCore<CharMap> ::value );
|
||||||
|
CHECK (false == is_StateCore<BoolList> ::value );
|
||||||
|
CHECK (false == is_StateCore<ShortDeque>::value );
|
||||||
|
CHECK (false == is_StateCore<CustomCont>::value );
|
||||||
|
|
||||||
|
CHECK (false == is_StateCore<LumieraRangeIter> ::value );
|
||||||
|
CHECK (false == is_StateCore<LumieraFilteredIter> ::value );
|
||||||
|
CHECK (false == is_StateCore<LumieraTransformedIter>::value );
|
||||||
|
CHECK (false == is_StateCore<CustomLumieraIter> ::value );
|
||||||
|
|
||||||
|
CHECK ( true == is_StateCore<CustomStateCore>::value );
|
||||||
|
CHECK ( true == is_StateCore<LumieraCoreIter>::value );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -219,8 +219,8 @@ namespace interact {
|
||||||
{
|
{
|
||||||
return Symbol{id};
|
return Symbol{id};
|
||||||
};
|
};
|
||||||
return depth==UIC_PERSP? buildNavigator (node, depth, singleValIterator (internedString (node.getType())))
|
return depth==UIC_PERSP? buildNavigator (node, depth, singletonIter (internedString (node.getType())))
|
||||||
: buildNavigator (node, depth, transformIterator (node.keys(), internedString));
|
: buildNavigator (node, depth, transformIter (node.keys(), internedString));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ using std::string;
|
||||||
|
|
||||||
using lib::Symbol;
|
using lib::Symbol;
|
||||||
using lib::append_all;
|
using lib::append_all;
|
||||||
using lib::transformIterator;
|
using lib::transformIter;
|
||||||
using lib::diff::Rec;
|
using lib::diff::Rec;
|
||||||
using lib::diff::GenNode;
|
using lib::diff::GenNode;
|
||||||
using lib::diff::DataCap;
|
using lib::diff::DataCap;
|
||||||
|
|
@ -487,7 +487,7 @@ namespace test{
|
||||||
{
|
{
|
||||||
EventLog::ArgSeq strings;
|
EventLog::ArgSeq strings;
|
||||||
strings.reserve (argData.childSize());
|
strings.reserve (argData.childSize());
|
||||||
append_all (transformIterator (childData (argData.scope())
|
append_all (transformIter (childData (argData.scope())
|
||||||
, util::toString<DataCap>)
|
, util::toString<DataCap>)
|
||||||
,strings);
|
,strings);
|
||||||
return strings;
|
return strings;
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ namespace test {
|
||||||
|
|
||||||
using ::test::randTime;
|
using ::test::randTime;
|
||||||
using steam::fixture::Segment;
|
using steam::fixture::Segment;
|
||||||
using lib::singleValIterator;
|
using lib::singletonIter;
|
||||||
using util::isSameObject;
|
using util::isSameObject;
|
||||||
using util::seqTuple;
|
using util::seqTuple;
|
||||||
|
|
||||||
|
|
@ -351,7 +351,7 @@ namespace test {
|
||||||
.genNode())
|
.genNode())
|
||||||
.genNode()};
|
.genNode()};
|
||||||
|
|
||||||
auto start = singleValIterator (mockSegs[Time::ZERO].jobTicket(0));
|
auto start = singletonIter (mockSegs[Time::ZERO].jobTicket(0));
|
||||||
|
|
||||||
auto it = lib::explore(start)
|
auto it = lib::explore(start)
|
||||||
.expand ([](JobTicket& ticket)
|
.expand ([](JobTicket& ticket)
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue