//------------------------------------------------------------------------------ /* This file is part of Beast: https://github.com/vinniefalco/Beast Copyright 2013, Vinnie Falco Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ //============================================================================== #include "../../../modules/beast_core/beast_core.h" // for UnitTest #include "../../chrono/manual_clock.h" #include "../aged_set.h" #include "../aged_map.h" #include "../aged_multiset.h" #include "../aged_multimap.h" #include "../aged_unordered_set.h" #include "../aged_unordered_map.h" #include "../aged_unordered_multiset.h" #include "../aged_unordered_multimap.h" #ifndef BEAST_AGED_UNORDERED_NO_ALLOC_DEFAULTCTOR # ifdef _MSC_VER # define BEAST_AGED_UNORDERED_NO_ALLOC_DEFAULTCTOR 0 # else # define BEAST_AGED_UNORDERED_NO_ALLOC_DEFAULTCTOR 1 # endif #endif #ifndef BEAST_CONTAINER_EXTRACT_NOREF # ifdef _MSC_VER # define BEAST_CONTAINER_EXTRACT_NOREF 1 # else # define BEAST_CONTAINER_EXTRACT_NOREF 1 # endif #endif namespace beast { class aged_associative_container_TestsBase : public UnitTest { public: template struct CompT { explicit CompT (int) { } CompT (CompT const&) { } bool operator() (T const& lhs, T const& rhs) const { return m_less (lhs, rhs); } private: CompT () = delete; std::less m_less; }; template class HashT { public: explicit HashT (int) { } std::size_t operator() (T const& t) const { return m_hash (t); } private: HashT() = delete; std::hash m_hash; }; template struct EqualT { public: explicit EqualT (int) { } bool operator() (T const& lhs, T const& rhs) const { return m_eq (lhs, rhs); } private: EqualT() = delete; std::equal_to m_eq; }; template struct AllocT { typedef T value_type; //typedef propagate_on_container_swap : std::true_type::type; template struct rebind { typedef AllocT other; }; explicit AllocT (int) { } AllocT (AllocT const&) { } template AllocT (AllocT const&) { } template bool operator== (AllocT const&) const { return true; } T* allocate (std::size_t n, T const* = 0) { return static_cast ( ::operator new (n * sizeof(T))); } void deallocate (T* p, std::size_t) { ::operator delete (p); } #if ! BEAST_AGED_UNORDERED_NO_ALLOC_DEFAULTCTOR AllocT () { } #else private: AllocT() = delete; #endif }; //-------------------------------------------------------------------------- // ordered template class MaybeUnordered : public Base { public: typedef std::less Comp; typedef CompT MyComp; protected: static std::string name_ordered_part() { return ""; } }; // unordered template class MaybeUnordered : public Base { public: typedef std::hash Hash; typedef std::equal_to Equal; typedef HashT MyHash; typedef EqualT MyEqual; protected: static std::string name_ordered_part() { return "unordered_"; } }; // unique template class MaybeMulti : public Base { public: protected: static std::string name_multi_part() { return ""; } }; // multi template class MaybeMulti : public Base { public: protected: static std::string name_multi_part() { return "multi"; } }; // set template class MaybeMap : public Base { public: typedef void T; typedef typename Base::Key Value; typedef std::vector Values; static typename Base::Key const& extract (Value const& value) { return value; } static Values values() { Values v { "apple", "banana", "cherry", "grape", "orange", }; return v; }; protected: static std::string name_map_part() { return "set"; } }; // map template class MaybeMap : public Base { public: typedef int T; typedef std::pair Value; typedef std::vector Values; static typename Base::Key const& extract (Value const& value) { return value.first; } static Values values() { Values v { std::make_pair ("apple", 1), std::make_pair ("banana", 2), std::make_pair ("cherry", 3), std::make_pair ("grape", 4), std::make_pair ("orange", 5) }; return v; }; protected: static std::string name_map_part() { return "map"; } }; //-------------------------------------------------------------------------- // ordered template < class Base, bool IsUnordered = Base::is_unordered::value > struct ContType { template < class Compare = std::less , class Allocator = std::allocator > using Cont = detail::aged_ordered_container < Base::is_multi::value, Base::is_map::value, typename Base::Key, typename Base::T, typename Base::Dur, Compare, Allocator>; }; // unordered template < class Base > struct ContType { template < class Hash = std::hash , class KeyEqual = std::equal_to , class Allocator = std::allocator > using Cont = detail::aged_unordered_container < Base::is_multi::value, Base::is_map::value, typename Base::Key, typename Base::T, typename Base::Dur, Hash, KeyEqual, Allocator>; }; //-------------------------------------------------------------------------- struct TestTraitsBase { typedef std::string Key; typedef std::chrono::seconds Dur; typedef manual_clock Clock; }; template struct TestTraitsHelper : MaybeUnordered , IsMulti>, IsUnordered> { private: typedef MaybeUnordered , IsMulti>, IsUnordered> Base; public: using typename Base::Key; typedef std::integral_constant is_unordered; typedef std::integral_constant is_multi; typedef std::integral_constant is_map; typedef std::allocator Alloc; typedef AllocT MyAlloc; static std::string name() { return std::string ("aged_") + Base::name_ordered_part() + Base::name_multi_part() + Base::name_map_part(); } }; template struct TestTraits : TestTraitsHelper , ContType > { }; template static std::string name (Cont const&) { return TestTraits < Cont::is_unordered, Cont::is_multi, Cont::is_map>::name(); } template struct equal_value { bool operator() (typename Traits::Value const& lhs, typename Traits::Value const& rhs) { return Traits::extract (lhs) == Traits::extract (rhs); } }; template static std::list make_list (Cont const& c) { return std::list ( c.begin(), c.end()); } //-------------------------------------------------------------------------- // Compile time checks // void checkAliases () { typedef std::string Key; typedef int T; static_assert (std::is_same < aged_set , detail::aged_ordered_container >::value, "bad alias: aged_set"); static_assert (std::is_same < aged_multiset , detail::aged_ordered_container >::value, "bad alias: aged_multiset"); static_assert (std::is_same < aged_map , detail::aged_ordered_container >::value, "bad alias: aged_map"); static_assert (std::is_same < aged_multimap , detail::aged_ordered_container >::value, "bad alias: aged_multimap"); static_assert (std::is_same < aged_unordered_set , detail::aged_unordered_container >::value, "bad alias: aged_unordered_set"); static_assert (std::is_same < aged_unordered_multiset , detail::aged_unordered_container >::value, "bad alias: aged_unordered_multiset"); static_assert (std::is_same < aged_unordered_map , detail::aged_unordered_container >::value, "bad alias: aged_unordered_map"); static_assert (std::is_same < aged_unordered_multimap , detail::aged_unordered_container >::value, "bad alias: aged_unordered_multimap"); } //-------------------------------------------------------------------------- template < class Container, class Values > typename std::enable_if < Container::is_map::value && ! Container::is_multi::value>::type checkMapContents (Container& c, Values const& v); template < class Container, class Values > typename std::enable_if ::type checkMapContents (Container, Values const&) { } // unordered template < class C, class Values > typename std::enable_if < std::remove_reference ::type::is_unordered::value>::type checkUnorderedContentsRefRef (C&& c, Values const& v); template < class C, class Values > typename std::enable_if ::type::is_unordered::value>::type checkUnorderedContentsRefRef (C&&, Values const&) { } template void checkContentsRefRef (C&& c, Values const& v); template void checkContents (Cont& c, Values const& v); template void checkContents (Cont& c); //-------------------------------------------------------------------------- // ordered template typename std::enable_if ::type testConstructEmpty (); // unordered template typename std::enable_if ::type testConstructEmpty (); // ordered template typename std::enable_if ::type testConstructRange (); // unordered template typename std::enable_if ::type testConstructRange (); // ordered template typename std::enable_if ::type testConstructInitList (); // unordered template typename std::enable_if ::type testConstructInitList (); //-------------------------------------------------------------------------- template void testCopyMove (); //-------------------------------------------------------------------------- template void checkInsertCopy (Container& c, Values const& v); template void checkInsertMove (Container& c, Values const& v); template void checkInsertHintCopy (Container& c, Values const& v); template void checkInsertHintMove (Container& c, Values const& v); template void checkEmplace (Container& c, Values const& v); template void checkEmplaceHint (Container& c, Values const& v); template void testModifiers(); //-------------------------------------------------------------------------- template void testChronological (); //-------------------------------------------------------------------------- // map, unordered_map template typename std::enable_if ::type testArrayCreate(); template typename std::enable_if ::type testArrayCreate() { } //-------------------------------------------------------------------------- // ordered template typename std::enable_if ::type testCompare (); template typename std::enable_if ::type testCompare () { } //-------------------------------------------------------------------------- // ordered template typename std::enable_if ::type testObservers(); // unordered template typename std::enable_if ::type testObservers(); //-------------------------------------------------------------------------- template void testMaybeUnorderedMultiMap (); template void testMaybeUnorderedMulti(); template void testMaybeUnordered(); aged_associative_container_TestsBase () : UnitTest ( "aged_associative_container", "beast") { } }; //------------------------------------------------------------------------------ // Check contents via at() and operator[] // map, unordered_map template < class Container, class Values > typename std::enable_if < Container::is_map::value && ! Container::is_multi::value>::type aged_associative_container_TestsBase:: checkMapContents (Container& c, Values const& v) { if (v.empty()) { expect (c.empty()); expect (c.size() == 0); return; } try { // Make sure no exception is thrown for (auto const& e : v) c.at (e.first); for (auto const& e : v) expect (c.operator[](e.first) == e.second); } catch (std::out_of_range const&) { fail ("caught exception"); } } // unordered template < class C, class Values > typename std::enable_if < std::remove_reference ::type::is_unordered::value>::type aged_associative_container_TestsBase:: checkUnorderedContentsRefRef (C&& c, Values const& v) { typedef typename std::remove_reference ::type Cont; typedef TestTraits < Cont::is_unordered::value, Cont::is_multi::value, Cont::is_map::value > Traits; typedef typename Cont::size_type size_type; auto const hash (c.hash_function()); auto const key_eq (c.key_eq()); for (size_type i (0); i < c.bucket_count(); ++i) { auto const last (c.end(i)); for (auto iter (c.begin (i)); iter != last; ++iter) { auto const match (std::find_if (v.begin(), v.end(), [iter](typename Values::value_type const& e) { return Traits::extract (*iter) == Traits::extract (e); })); expect (match != v.end()); expect (key_eq (Traits::extract (*iter), Traits::extract (*match))); expect (hash (Traits::extract (*iter)) == hash (Traits::extract (*match))); } } } template void aged_associative_container_TestsBase:: checkContentsRefRef (C&& c, Values const& v) { typedef typename std::remove_reference ::type Cont; typedef TestTraits < Cont::is_unordered::value, Cont::is_multi::value, Cont::is_map::value > Traits; typedef typename Cont::size_type size_type; expect (c.size() == v.size()); expect (size_type (std::distance ( c.begin(), c.end())) == v.size()); expect (size_type (std::distance ( c.cbegin(), c.cend())) == v.size()); expect (size_type (std::distance ( c.chronological.begin(), c.chronological.end())) == v.size()); expect (size_type (std::distance ( c.chronological.cbegin(), c.chronological.cend())) == v.size()); expect (size_type (std::distance ( c.chronological.rbegin(), c.chronological.rend())) == v.size()); expect (size_type (std::distance ( c.chronological.crbegin(), c.chronological.crend())) == v.size()); checkUnorderedContentsRefRef (c, v); } template void aged_associative_container_TestsBase:: checkContents (Cont& c, Values const& v) { checkContentsRefRef (c, v); checkContentsRefRef (const_cast (c), v); checkMapContents (c, v); } template void aged_associative_container_TestsBase:: checkContents (Cont& c) { typedef TestTraits < Cont::is_unordered::value, Cont::is_multi::value, Cont::is_map::value > Traits; typedef typename Traits::Values Values; checkContents (c, Values()); } //------------------------------------------------------------------------------ // // Construction // //------------------------------------------------------------------------------ // ordered template typename std::enable_if ::type aged_associative_container_TestsBase:: testConstructEmpty () { typedef TestTraits Traits; typedef typename Traits::Value Value; typedef typename Traits::Key Key; typedef typename Traits::T T; typedef typename Traits::Dur Dur; typedef typename Traits::Comp Comp; typedef typename Traits::Alloc Alloc; typedef typename Traits::MyComp MyComp; typedef typename Traits::MyAlloc MyAlloc; typename Traits::Clock clock; beginTestCase (Traits::name() + " empty"); { typename Traits::template Cont c ( clock); checkContents (c); } { typename Traits::template Cont c ( clock, MyComp(1)); checkContents (c); } { typename Traits::template Cont c ( clock, MyAlloc(1)); checkContents (c); } { typename Traits::template Cont c ( clock, MyComp(1), MyAlloc(1)); checkContents (c); } } // unordered template typename std::enable_if ::type aged_associative_container_TestsBase:: testConstructEmpty () { typedef TestTraits Traits; typedef typename Traits::Value Value; typedef typename Traits::Key Key; typedef typename Traits::T T; typedef typename Traits::Dur Dur; typedef typename Traits::Hash Hash; typedef typename Traits::Equal Equal; typedef typename Traits::Alloc Alloc; typedef typename Traits::MyHash MyHash; typedef typename Traits::MyEqual MyEqual; typedef typename Traits::MyAlloc MyAlloc; typename Traits::Clock clock; beginTestCase (Traits::name() + " empty"); { typename Traits::template Cont c ( clock); checkContents (c); } { typename Traits::template Cont c ( clock, MyHash(1)); checkContents (c); } { typename Traits::template Cont c ( clock, MyEqual (1)); checkContents (c); } { typename Traits::template Cont c ( clock, MyAlloc (1)); checkContents (c); } { typename Traits::template Cont c ( clock, MyHash(1), MyEqual(1)); checkContents (c); } { typename Traits::template Cont c ( clock, MyHash(1), MyAlloc(1)); checkContents (c); } { typename Traits::template Cont c ( clock, MyEqual(1), MyAlloc(1)); checkContents (c); } { typename Traits::template Cont c ( clock, MyHash(1), MyEqual(1), MyAlloc(1)); checkContents (c); } } // ordered template typename std::enable_if ::type aged_associative_container_TestsBase:: testConstructRange () { typedef TestTraits Traits; typedef typename Traits::Value Value; typedef typename Traits::Key Key; typedef typename Traits::T T; typedef typename Traits::Dur Dur; typedef typename Traits::Comp Comp; typedef typename Traits::Alloc Alloc; typedef typename Traits::MyComp MyComp; typedef typename Traits::MyAlloc MyAlloc; typename Traits::Clock clock; auto const v (Traits::values()); beginTestCase (Traits::name() + " range"); { typename Traits::template Cont c ( v.begin(), v.end(), clock); checkContents (c, v); } { typename Traits::template Cont c ( v.begin(), v.end(), clock, MyComp(1)); checkContents (c, v); } { typename Traits::template Cont c ( v.begin(), v.end(), clock, MyAlloc(1)); checkContents (c, v); } { typename Traits::template Cont c ( v.begin(), v.end(), clock, MyComp(1), MyAlloc(1)); checkContents (c, v); } // swap { typename Traits::template Cont c1 ( v.begin(), v.end(), clock); typename Traits::template Cont c2 ( clock); std::swap (c1, c2); checkContents (c2, v); } } // unordered template typename std::enable_if ::type aged_associative_container_TestsBase:: testConstructRange () { typedef TestTraits Traits; typedef typename Traits::Value Value; typedef typename Traits::Key Key; typedef typename Traits::T T; typedef typename Traits::Dur Dur; typedef typename Traits::Hash Hash; typedef typename Traits::Equal Equal; typedef typename Traits::Alloc Alloc; typedef typename Traits::MyHash MyHash; typedef typename Traits::MyEqual MyEqual; typedef typename Traits::MyAlloc MyAlloc; typename Traits::Clock clock; auto const v (Traits::values()); beginTestCase (Traits::name() + " range"); { typename Traits::template Cont c ( v.begin(), v.end(), clock); checkContents (c, v); } { typename Traits::template Cont c ( v.begin(), v.end(), clock, MyHash(1)); checkContents (c, v); } { typename Traits::template Cont c ( v.begin(), v.end(), clock, MyEqual (1)); checkContents (c, v); } { typename Traits::template Cont c ( v.begin(), v.end(), clock, MyAlloc (1)); checkContents (c, v); } { typename Traits::template Cont c ( v.begin(), v.end(), clock, MyHash(1), MyEqual(1)); checkContents (c, v); } { typename Traits::template Cont c ( v.begin(), v.end(), clock, MyHash(1), MyAlloc(1)); checkContents (c, v); } { typename Traits::template Cont c ( v.begin(), v.end(), clock, MyEqual(1), MyAlloc(1)); checkContents (c, v); } { typename Traits::template Cont c ( v.begin(), v.end(), clock, MyHash(1), MyEqual(1), MyAlloc(1)); checkContents (c, v); } } // ordered template typename std::enable_if ::type aged_associative_container_TestsBase:: testConstructInitList () { typedef TestTraits Traits; typedef typename Traits::Value Value; typedef typename Traits::Key Key; typedef typename Traits::T T; typedef typename Traits::Dur Dur; typedef typename Traits::Comp Comp; typedef typename Traits::Alloc Alloc; typedef typename Traits::MyComp MyComp; typedef typename Traits::MyAlloc MyAlloc; typename Traits::Clock clock; beginTestCase (Traits::name() + " init-list"); // VFALCO TODO pass(); } // unordered template typename std::enable_if ::type aged_associative_container_TestsBase:: testConstructInitList () { typedef TestTraits Traits; typedef typename Traits::Value Value; typedef typename Traits::Key Key; typedef typename Traits::T T; typedef typename Traits::Dur Dur; typedef typename Traits::Hash Hash; typedef typename Traits::Equal Equal; typedef typename Traits::Alloc Alloc; typedef typename Traits::MyHash MyHash; typedef typename Traits::MyEqual MyEqual; typedef typename Traits::MyAlloc MyAlloc; typename Traits::Clock clock; beginTestCase (Traits::name() + " init-list"); // VFALCO TODO pass(); } //------------------------------------------------------------------------------ // // Copy/Move construction and assign // //------------------------------------------------------------------------------ template void aged_associative_container_TestsBase:: testCopyMove () { typedef TestTraits Traits; typedef typename Traits::Value Value; typedef typename Traits::Alloc Alloc; typename Traits::Clock clock; auto const v (Traits::values()); beginTestCase (Traits::name() + " copy/move"); // copy { typename Traits::template Cont <> c ( v.begin(), v.end(), clock); typename Traits::template Cont <> c2 (c); checkContents (c, v); checkContents (c2, v); expect (c == c2); unexpected (c != c2); } { typename Traits::template Cont <> c ( v.begin(), v.end(), clock); typename Traits::template Cont <> c2 (c, Alloc()); checkContents (c, v); checkContents (c2, v); expect (c == c2); unexpected (c != c2); } { typename Traits::template Cont <> c ( v.begin(), v.end(), clock); typename Traits::template Cont <> c2 ( clock); c2 = c; checkContents (c, v); checkContents (c2, v); expect (c == c2); unexpected (c != c2); } // move { typename Traits::template Cont <> c ( v.begin(), v.end(), clock); typename Traits::template Cont <> c2 ( std::move (c)); checkContents (c2, v); } { typename Traits::template Cont <> c ( v.begin(), v.end(), clock); typename Traits::template Cont <> c2 ( std::move (c), Alloc()); checkContents (c2, v); } { typename Traits::template Cont <> c ( v.begin(), v.end(), clock); typename Traits::template Cont <> c2 ( clock); c2 = std::move (c); checkContents (c2, v); } } //------------------------------------------------------------------------------ // // Modifiers // //------------------------------------------------------------------------------ template void aged_associative_container_TestsBase:: checkInsertCopy (Container& c, Values const& v) { for (auto const& e : v) c.insert (e); checkContents (c, v); } template void aged_associative_container_TestsBase:: checkInsertMove (Container& c, Values const& v) { Values v2 (v); for (auto& e : v2) c.insert (std::move (e)); checkContents (c, v); } template void aged_associative_container_TestsBase:: checkInsertHintCopy (Container& c, Values const& v) { for (auto const& e : v) c.insert (c.cend(), e); checkContents (c, v); } template void aged_associative_container_TestsBase:: checkInsertHintMove (Container& c, Values const& v) { Values v2 (v); for (auto& e : v2) c.insert (c.cend(), std::move (e)); checkContents (c, v); } template void aged_associative_container_TestsBase:: checkEmplace (Container& c, Values const& v) { for (auto const& e : v) c.emplace (e); checkContents (c, v); } template void aged_associative_container_TestsBase:: checkEmplaceHint (Container& c, Values const& v) { for (auto const& e : v) c.emplace_hint (c.cend(), e); checkContents (c, v); } template void aged_associative_container_TestsBase:: testModifiers() { typedef TestTraits Traits; typename Traits::Clock clock; auto const v (Traits::values()); auto const l (make_list (v)); beginTestCase (Traits::name() + " modify"); { typename Traits::template Cont <> c (clock); checkInsertCopy (c, v); } { typename Traits::template Cont <> c (clock); checkInsertCopy (c, l); } { typename Traits::template Cont <> c (clock); checkInsertMove (c, v); } { typename Traits::template Cont <> c (clock); checkInsertMove (c, l); } { typename Traits::template Cont <> c (clock); checkInsertHintCopy (c, v); } { typename Traits::template Cont <> c (clock); checkInsertHintCopy (c, l); } { typename Traits::template Cont <> c (clock); checkInsertHintMove (c, v); } { typename Traits::template Cont <> c (clock); checkInsertHintMove (c, l); } } //------------------------------------------------------------------------------ // // Chronological ordering // //------------------------------------------------------------------------------ template void aged_associative_container_TestsBase:: testChronological () { typedef TestTraits Traits; typedef typename Traits::Value Value; typename Traits::Clock clock; auto const v (Traits::values()); beginTestCase (Traits::name() + " chronological"); typename Traits::template Cont <> c ( v.begin(), v.end(), clock); expect (std::equal ( c.chronological.cbegin(), c.chronological.cend(), v.begin(), v.end(), equal_value ())); for (auto iter (v.rbegin()); iter != v.rend(); ++iter) { auto found (c.find (Traits::extract (*iter))); expect (found != c.cend()); if (found == c.cend()) return; c.touch (found); } expect (std::equal ( c.chronological.cbegin(), c.chronological.cend(), v.rbegin(), v.rend(), equal_value ())); } //------------------------------------------------------------------------------ // // Element creation via operator[] // //------------------------------------------------------------------------------ // map, unordered_map template typename std::enable_if ::type aged_associative_container_TestsBase:: testArrayCreate() { typedef TestTraits Traits; typename Traits::Clock clock; auto v (Traits::values()); beginTestCase (Traits::name() + " array create"); { // Copy construct key typename Traits::template Cont <> c (clock); for (auto e : v) c [e.first] = e.second; checkContents (c, v); } { // Move construct key typename Traits::template Cont <> c (clock); for (auto e : v) c [std::move (e.first)] = e.second; checkContents (c, v); } } //------------------------------------------------------------------------------ // // Container-wide comparison // //------------------------------------------------------------------------------ // ordered template typename std::enable_if ::type aged_associative_container_TestsBase:: testCompare () { typedef TestTraits Traits; typedef typename Traits::Value Value; typename Traits::Clock clock; auto const v (Traits::values()); beginTestCase (Traits::name() + " array create"); typename Traits::template Cont <> c1 ( v.begin(), v.end(), clock); typename Traits::template Cont <> c2 ( v.begin(), v.end(), clock); c2.erase (c2.cbegin()); expect (c1 != c2); unexpected (c1 == c2); expect (c1 < c2); expect (c1 <= c2); unexpected (c1 > c2); unexpected (c1 >= c2); } //------------------------------------------------------------------------------ // // Observers // //------------------------------------------------------------------------------ // ordered template typename std::enable_if ::type aged_associative_container_TestsBase:: testObservers() { typedef TestTraits Traits; typename Traits::Clock clock; beginTestCase (Traits::name() + " observers"); typename Traits::template Cont <> c (clock); c.key_comp(); c.value_comp(); pass(); } // unordered template typename std::enable_if ::type aged_associative_container_TestsBase:: testObservers() { typedef TestTraits Traits; typename Traits::Clock clock; beginTestCase (Traits::name() + " observers"); typename Traits::template Cont <> c (clock); c.hash_function(); c.key_eq(); pass(); } //------------------------------------------------------------------------------ // // Matrix // //------------------------------------------------------------------------------ template void aged_associative_container_TestsBase:: testMaybeUnorderedMultiMap () { typedef TestTraits Traits; testConstructEmpty (); testConstructRange (); testConstructInitList (); testCopyMove (); testModifiers (); testChronological (); testArrayCreate (); testCompare (); testObservers (); } template void aged_associative_container_TestsBase:: testMaybeUnorderedMulti() { testMaybeUnorderedMultiMap (); testMaybeUnorderedMultiMap (); } template void aged_associative_container_TestsBase:: testMaybeUnordered() { testMaybeUnorderedMulti (); testMaybeUnorderedMulti (); } //------------------------------------------------------------------------------ class aged_associative_container_Tests : public aged_associative_container_TestsBase { public: void runTest () { checkAliases (); testMaybeUnordered (); testMaybeUnordered (); } }; static aged_associative_container_Tests aged_associative_container_tests; }