// //$ bin/bin/g++ -std=c++0x -o foo test_forward_list.cpp //$ LD_LIBRARY_PATH=bin/lib64:$LD_LIBRARY_PATH ./foo // #include #include #include #include "forward_list" template> void vomit(const std::forward_list& l) { std::cout << " "; std::ostream_iterator out(std::cout, " "); std::copy(l.begin(), l.end(), out); std::cout << std::endl; } // Test comparison predicate. template class Mod { public: Mod(const Num & mod) { m = mod; } bool operator()(const Num i, const Num j) { return i%m == j%m; } private: Num m; }; void test01(void) { std::cout.precision(2); std::cout.setf(std::ios_base::showpoint); // Default ctor. std::cout << std::endl << "Default ctor" << std::endl; std::forward_list fld; std::cout << " list:"; vomit(fld); std::cout << " empty: " << fld.empty() << std::endl; // Number of default values ctor. std::cout << std::endl << "Number of default values ctor" << std::endl; std::forward_list flvd(10); std::cout << " list:"; vomit(flvd); std::cout << " empty: " << flvd.empty() << std::endl; // Number of specified values ctor. std::cout << std::endl << "Number of specified values ctor" << std::endl; std::forward_list flv(10, 5.0F); std::cout << " list:"; vomit(flv); // Iterator range ctor. std::cout << std::endl << "Iterator range ctor" << std::endl; int i[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; std::forward_list fl(i, i+10); std::cout << " list:"; vomit(fl); // Copy ctor. std::cout << std::endl << "Copy ctor" << std::endl; std::forward_list flc(fl); std::cout << " list:"; vomit(flc); // Move ctor. std::cout << std::endl << "Move ctor" << std::endl; std::forward_list flm(std::move(fl)); std::cout << " list:"; vomit(flm); // Initializer list ctor. std::cout << std::endl << "Initializer list ctor" << std::endl; std::forward_list flil({1.0, 2.0, 3.0, 4.0, 5.0}); std::cout << " list:"; vomit(flil); // Assign from list. std::cout << std::endl << "Assign from list" << std::endl; std::forward_list fla; std::cout << "before:"; vomit(fla); fla = fl; std::cout << " after:"; vomit(fla); // Assign from list with move. std::cout << std::endl << "Assign from list with move" << std::endl; std::forward_list flam; std::cout << "before:"; vomit(flam); std::cout << "before:"; vomit(fla); flam = std::move(fla); std::cout << " after:"; vomit(flam); std::cout << " after:"; vomit(fla); // Assign from initializer list. std::cout << std::endl << "Assign from initializer list" << std::endl; std::forward_list flail(15L); std::cout << "before:"; vomit(flail); flail = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; std::cout << " after:"; vomit(flail); // Push front. std::cout << std::endl << "Push front" << std::endl; std::cout << "before:"; vomit(fl); fl.push_front(1000000); std::cout << " after:"; vomit(fl); // Push front with move. std::cout << std::endl << "Push front with move" << std::endl; std::cout << "before:"; vomit(fl); fl.push_front(std::move(2000000)); std::cout << " after:"; vomit(fl); // Pop front. std::cout << std::endl << "Pop front ..." << std::endl; std::cout << "before:"; vomit(fl); fl.pop_front(); std::cout << " after:"; vomit(fl); std::cout << std::endl << "... and again" << std::endl; fl.pop_front(); std::cout << " after:"; vomit(fl); // Insert after using before begin. std::cout << std::endl << "Insert after using before begin" << std::endl; std::cout << "before:"; vomit(fl); fl.insert_after(fl.before_begin(), 0); std::cout << " after:"; vomit(fl); // Front. std::cout << std::endl << "Front" << std::endl; std::cout << "front: " << fl.front() << std::endl; // Max size. std::cout << std::endl << "Max size" << std::endl; std::cout << "max_size: " << fl.max_size() << std::endl; // Insert after begin. std::cout << std::endl << "Insert after begin" << std::endl; std::cout << "before:"; vomit(fl); std::forward_list::const_iterator pos0 = fl.cbegin(); fl.insert_after(pos0, 42); std::cout << " after:"; vomit(fl); std::cout << " pos0: " << *pos0 << std::endl; ++pos0; std::cout << "++pos0: " << *pos0 << std::endl; // Remove one value. std::cout << std::endl << "Remove one value" << std::endl; std::cout << "before:"; vomit(fl); fl.remove(42); std::cout << " after:"; vomit(fl); // Remove values based on predicate. std::cout << std::endl << "Remove values based on predicate" << std::endl; std::cout << "before:"; vomit(fl); fl.remove_if(std::bind2nd(std::less(),5)); std::cout << " after:"; vomit(fl); // Insert after with number and value. std::cout << std::endl << "Insert after with number and value" << std::endl; std::cout << "before:"; vomit(fl); std::forward_list::const_iterator pos1 = fl.cbegin(); ++pos1; std::cout << " pos1: " << *pos1 << std::endl; // Note: Calling l.insert_after(pos1, 5, 42); without the long five // gets resolved to the iterator range version and fails to compile! fl.insert_after(pos1, 5L, 42); std::cout << " after:"; vomit(fl); // Insert after with iterator range. std::cout << std::endl << "Insert after with iterator range" << std::endl; std::cout << "before:"; vomit(fl); std::forward_list::const_iterator pos2 = fl.cbegin(); ++pos2; std::cout << " pos2: " << *pos2 << std::endl; int i2[3] = {666, 777, 888}; fl.insert_after(pos2, i2, i2+3); std::cout << " after:"; vomit(fl); // Insert after with initializer list. std::cout << std::endl << "Insert after with initializer list" << std::endl; std::cout << "before:"; vomit(fl); std::forward_list::const_iterator pos3 = fl.cbegin(); ++pos3; std::cout << " pos3: " << *pos3 << std::endl; fl.insert_after(pos3, {-1, -2, -3, -4, -5}); std::cout << " after:"; vomit(fl); // Erase after one value. std::cout << std::endl << "Erase after one value" << std::endl; std::cout << "before:"; vomit(fl); std::forward_list::const_iterator pos4 = fl.cbegin(); ++pos4; std::cout << " pos4: " << *pos4 << std::endl; std::forward_list::iterator next4 = fl.erase_after(pos4); std::cout << " after:"; vomit(fl); std::cout << " next4: " << *next4 << std::endl; // Erase after with iterator range. std::cout << std::endl << "Erase after with iterator range" << std::endl; std::cout << "before:"; vomit(fl); std::forward_list::const_iterator pos5 = fl.cbegin(); ++pos5; std::cout << " pos5: " << *pos5 << std::endl; std::forward_list::iterator stop5 = fl.begin(); ++stop5; ++stop5; ++stop5; ++stop5; std::cout << " stop5: " << *stop5 << std::endl; std::forward_list::iterator next5 = fl.erase_after(pos5, stop5); std::cout << " after:"; vomit(fl); std::cout << " next5: " << *next5 << std::endl; // Swap. std::cout << std::endl << "Swap" << std::endl; std::cout << "before:"; vomit(fl); std::forward_list fl2(i, i+10); std::cout << "before:"; vomit(fl2); fl.swap(fl2); std::cout << " after:"; vomit(fl); std::cout << " after:"; vomit(fl2); // Resize. std::cout << std::endl << "Resize" << std::endl; std::cout << "before:"; vomit(fl); fl.resize(12); std::cout << " after:"; vomit(fl); // Resize. std::cout << std::endl << "Resize" << std::endl; std::cout << "before:"; vomit(fl); fl.resize(15); std::cout << " after:"; vomit(fl); // Resize with value. std::cout << std::endl << "Resize with value" << std::endl; std::cout << "before:"; vomit(fl); fl.resize(18, 9); std::cout << " after:"; vomit(fl); // Emplace front. std::cout << std::endl << "Emplace front" << std::endl; std::cout << "before:"; vomit(fl); fl.emplace_front(99); std::cout << " after:"; vomit(fl); // Emplace after. std::cout << std::endl << "Emplace after" << std::endl; std::cout << "before:"; vomit(fl); std::forward_list::const_iterator pos6 = fl.cbegin(); ++pos6; fl.emplace_after(pos6, 99); std::cout << " after:"; vomit(fl); // Unique. std::cout << std::endl << "Unique" << std::endl; std::cout << "before:"; vomit(fl); fl.unique(); std::cout << " after:"; vomit(fl); // Unique with predicate. std::cout << std::endl << "Unique with predicate" << std::endl; std::cout << "before:"; vomit(fl); fl.unique(Mod(111)); std::cout << " after:"; vomit(fl); // Clear. std::cout << std::endl << "Clear" << std::endl; std::cout << "before:"; vomit(fl); fl.clear(); std::cout << " after:"; vomit(fl); return; } template class Comp { public: Comp(const Num & num) { n = num; } bool operator()(const Num i, const Num j) { return (n * i) < (n * j); } private: Num n; }; // // Small test rig with three test orders. The list length 13 is // chosen because that means some passes will have an extra list at // the end and some will not. // void test02(void) { const unsigned int n = 13; int order[][n] = { { 0,1,2,3,4,5,6,7,8,9,10,11,12 }, { 6,2,8,4,11,1,12,7,3,9,5,0,10 }, { 12,11,10,9,8,7,6,5,4,3,2,1,0 }, }; for (int i = 0; i < sizeof(order)/sizeof(*order); ++i) { std::forward_list head(order[i], order[i] + n); std::cout << std::endl << "Sort" << std::endl; std::cout << "before:"; vomit(head); head.sort(); std::cout << " after:"; vomit(head); } for (int i = 0; i < sizeof(order)/sizeof(*order); ++i) { std::forward_list head(order[i], order[i] + n); std::cout << std::endl << "Sort with compare functor" << std::endl; std::cout << "before:"; vomit(head); Comp comp(-1); head.sort( comp ); std::cout << " after:"; vomit(head); } // Reverse. std::cout << std::endl << "Reverse" << std::endl; std::forward_list fl(order[0], order[0] + n); std::cout << "before:"; vomit(fl); fl.reverse(); std::cout << " after:"; vomit(fl); return; } void test03(void) { std::forward_list a = {0.0, 1.0, 2.0, 3.0, 4.0}; std::forward_list b = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0}; std::cout << std::endl << "Comparison" << std::endl; std::cout << " a:"; vomit(a); std::cout << " b:"; vomit(b); std::cout << std::endl << "a == b : " << (a == b); std::cout << std::endl << "a < b : " << (a < b); std::cout << std::endl << "a != b : " << (a != b); std::cout << std::endl << "a > b : " << (a > b); std::cout << std::endl << "a >= b : " << (a >= b); std::cout << std::endl << "a <= b : " << (a <= b); std::cout << std::endl; std::cout << std::endl << "b == a : " << (b == a); std::cout << std::endl << "b < a : " << (b < a); std::cout << std::endl << "b != a : " << (b != a); std::cout << std::endl << "b > a : " << (b > a); std::cout << std::endl << "b >= a : " << (b >= a); std::cout << std::endl << "b <= a : " << (b <= a); std::cout << std::endl; return; } void test04(void) { std::forward_list a = {0.0, 1.0, 2.0, 3.0, 4.0}; std::forward_list x = {666.0, 777.0, 888.0}; std::forward_list y = {10.0, 11.0, 12.0, 13.0, 14.0, 15.0}; std::forward_list z = {42.0, 43.0, 44.0}; // Transfer whole list. std::forward_list::const_iterator posa = a.cbefore_begin(); std::cout << std::endl << "Transfer whole list (before begin)" << std::endl; //std::cout << " posa: " << *posa << std::endl; std::cout << "before a:"; vomit(a); std::cout << "before x:"; vomit(x); a.splice_after(posa, x); std::cout << " after a:"; vomit(a); std::cout << " after x:"; vomit(x); // Transfer iterator range. ++posa; std::forward_list::const_iterator befy = y.cbefore_begin(); ++befy; std::forward_list::const_iterator endy = befy; ++endy; ++endy; ++endy; std::cout << std::endl << "Transfer iterator range" << std::endl; std::cout << " posa: " << *posa << std::endl; std::cout << " befy: " << *befy << std::endl; std::cout << " endy: " << *endy << std::endl; std::cout << "before a:"; vomit(a); std::cout << "before y:"; vomit(y); a.splice_after(posa, y, befy, endy); std::cout << " after a:"; vomit(a); std::cout << " after y:"; vomit(y); // Transfer element. ++posa; std::forward_list::const_iterator befz = z.begin(); std::cout << std::endl << "Transfer element" << std::endl; std::cout << " posa: " << *posa << std::endl; std::cout << "before a:"; vomit(a); std::cout << "before z:"; vomit(z); a.splice_after(posa, z, befz); std::cout << " after a:"; vomit(a); std::cout << " after z:"; vomit(z); } void test05(void) { std::forward_list a = {0.0, 1.0, 2.0, 3.0, 4.0}; std::forward_list b = {1.0, 2.0, 3.0, 4.0, 4.0, 5.0}; std::cout << std::endl << "Merge" << std::endl; std::cout << " a:"; vomit(a); std::cout << " b:"; vomit(b); a.merge(b); std::cout << " a:"; vomit(a); std::cout << " b:"; vomit(b); return; } int main(int, char**) { std::cout.setf( std::ios::boolalpha ); test01(); test02(); test03(); test04(); test05(); return 0; }