/* IterableClassification(Test) - detecting iterability of a generic type Copyright (C) 2010, Hermann Vosseler   **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   Free Software Foundation; either version 2 of the License, or (at your   option) any later version. See the file COPYING for further details. * *****************************************************************/ /** @file iterable-classification-test.cpp ** 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 "lib/meta/trait.hpp" #include "lib/diff/record.hpp" #include "lib/time/timevalue.hpp" #include "lib/itertools.hpp" #include #include #include #include #include #include using std::string; using std::vector; using std::declval; using lib::time::TimeVar; namespace lib { namespace meta { namespace test { namespace { // a custom test container.... /// @note: a bare type definition is sufficient here.... struct TestSource { TestSource(uint num); using RawIter = vector::iterator; using iterator = RangeIter; iterator begin() ; iterator end() ; }; 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 /*******************************************************************************//** * @test verify the (static) classification/detection of iterables. * Using some SFINAE trickery, it is possible to detect the following * - a _STL-like container_ with `begin()` and `end()` * - a _Lumiera Forward Iterator_ * - a _State Core_ * 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. * @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 { void run (Arg) { // define a bunch of STL containers using TimeVector = std::vector; using LongSet = std::multiset ; using CharMap = std::map ; using BoolList = std::list ; using ShortDeque = std::deque ; using CustomCont = TestSource ; // some types that comply with the "Lumiera Forward Iterator" concept using LumieraRangeIter = TestSource::iterator; using LumieraFilteredIter = decltype( filteredSource (declval()) ); using LumieraTransformedIter = decltype( transformedSource (declval()) ); using CustomLumieraIter = diff::Record::iterator; // some types that comply with the "State Core" concept using CustomStateCore = DummyCore; using LumieraCoreIter = IterableDecorator; // detect STL iteration CHECK ( true == can_STL_ForEach::value ); CHECK ( true == can_STL_ForEach ::value ); CHECK ( true == can_STL_ForEach ::value ); CHECK ( true == can_STL_ForEach ::value ); CHECK ( true == can_STL_ForEach::value ); CHECK ( true == can_STL_ForEach::value ); CHECK (false == can_STL_ForEach ::value ); CHECK (false == can_STL_ForEach ::value ); CHECK (false == can_STL_ForEach::value ); CHECK (false == can_STL_ForEach ::value ); CHECK (false == can_STL_ForEach::value ); CHECK (false == can_STL_ForEach::value ); // detect Lumiera Forward Iterator CHECK (false == can_IterForEach::value ); CHECK (false == can_IterForEach ::value ); CHECK (false == can_IterForEach ::value ); CHECK (false == can_IterForEach ::value ); CHECK (false == can_IterForEach::value ); CHECK (false == can_IterForEach::value ); CHECK ( true == can_IterForEach ::value ); CHECK ( true == can_IterForEach ::value ); CHECK ( true == can_IterForEach::value ); CHECK ( true == can_IterForEach ::value ); CHECK (false == can_IterForEach::value ); CHECK ( true == can_IterForEach::value ); // Note: Lumiera iterator capability added as wrapper // detect State Core CHECK (false == is_StateCore::value ); CHECK (false == is_StateCore ::value ); CHECK (false == is_StateCore ::value ); CHECK (false == is_StateCore ::value ); CHECK (false == is_StateCore::value ); CHECK (false == is_StateCore::value ); CHECK (false == is_StateCore ::value ); CHECK (false == is_StateCore ::value ); CHECK (false == is_StateCore::value ); CHECK (false == is_StateCore ::value ); CHECK ( true == is_StateCore::value ); CHECK ( true == is_StateCore::value ); } }; /** Register this test class... */ LAUNCHER (IterableClassification_test, "unit common"); }}} // namespace lib::meta::test