#include <iostream>
#include <list>
#include <string>
#include <algorithm>
template<typename T>
void print_list(const std::list<T>& lst, const std::string& msg = "") {
if (!msg.empty())
std::cout << msg << ": ";
std::cout << "[ ";
for (const auto& elem : lst) {
std::cout << elem << " ";
}
std::cout << "]" << std::endl;
}
int main() {
std::cout << "========== 1. Construction and assignment ==========" << std::endl;
std::list<int> list1;
std::list<int> list2(5, 100);
std::list<int> list3 = {1, 2, 3, 4, 5};
std::list<int> list4(list3);
int arr[] = {10, 20, 30};
std::list<int> list5(std::begin(arr), std::end(arr));
print_list(list2, "list2 (5 elements of 100)");
print_list(list3, "list3");
print_list(list4, "list4 (copy of list3)");
print_list(list5, "list5 (constructed from array)");
list1.assign(3, 42);
print_list(list1, "list1 assign(3,42)");
list1.assign({7, 8, 9});
print_list(list1, "list1 assign({7,8,9})");
list1.assign(list5.begin(), list5.end());
print_list(list1, "list1 assign(iterator range)");
std::cout << "\n========== 2. Element access ==========" << std::endl;
std::list<std::string> str_list = {"apple", "banana", "cherry"};
print_list(str_list, "str_list");
std::cout << "front(): " << str_list.front() << std::endl;
std::cout << "back(): " << str_list.back() << std::endl;
std::cout << "\n========== 3. Iterators ==========" << std::endl;
std::list<int> iter_list = {10, 20, 30, 40, 50};
std::cout << "Forward iterator: ";
for (auto it = iter_list.begin(); it != iter_list.end(); ++it)
std::cout << *it << " ";
std::cout << std::endl;
std::cout << "Reverse iterator: ";
for (auto rit = iter_list.rbegin(); rit != iter_list.rend(); ++rit)
std::cout << *rit << " ";
std::cout << std::endl;
std::cout << "Const iterator (read-only): ";
for (auto cit = iter_list.cbegin(); cit != iter_list.cend(); ++cit)
std::cout << *cit << " ";
std::cout << std::endl;
std::cout << "\n========== 4. Capacity ==========" << std::endl;
std::list<double> cap_list = {1.1, 2.2, 3.3};
print_list(cap_list, "cap_list");
std::cout << "empty(): " << std::boolalpha << cap_list.empty() << std::endl;
std::cout << "size(): " << cap_list.size() << std::endl;
std::cout << "max_size(): " << cap_list.max_size() << std::endl;
cap_list.resize(5, 0.0);
print_list(cap_list, "resize(5, 0.0)");
cap_list.resize(2);
print_list(cap_list, "resize(2)");
std::cout << "\n========== 5. Insertion and deletion ==========" << std::endl;
std::list<int> mod_list;
mod_list.push_back(10);
mod_list.push_back(20);
mod_list.push_front(5);
mod_list.push_front(1);
print_list(mod_list, "after push_back/push_front");
mod_list.pop_back();
mod_list.pop_front();
print_list(mod_list, "after pop_back/pop_front");
auto it = mod_list.begin();
++it;
mod_list.insert(it, 15);
print_list(mod_list, "insert 15 before 20");
mod_list.insert(mod_list.end(), {25, 30});
print_list(mod_list, "insert multiple elements at end");
it = mod_list.begin();
++it;
it = mod_list.erase(it);
print_list(mod_list, "erase second element(15)");
auto first = mod_list.begin();
auto last = mod_list.begin();
std::advance(last, 2);
mod_list.erase(first, last);
print_list(mod_list, "erase first two elements");
mod_list.push_back(20);
mod_list.push_back(20);
mod_list.push_back(40);
print_list(mod_list, "after adding duplicate elements");
mod_list.remove(20);
print_list(mod_list, "after remove(20)");
mod_list.remove_if([](int n) { return n > 30; });
print_list(mod_list, "after remove_if(>30)");
mod_list.clear();
std::cout << "after clear size = " << mod_list.size() << std::endl;
std::list<std::pair<int, char>> emp_list;
emp_list.emplace_back(1, 'a');
emp_list.emplace_front(0, 'z');
auto eit = emp_list.begin();
++eit;
emp_list.emplace(eit, 2, 'b');
std::cout << "emplace example (pair): ";
for (const auto& p : emp_list)
std::cout << "(" << p.first << "," << p.second << ") ";
std::cout << std::endl;
std::cout << "\n========== 6. Special operations (splice, merge, sort, reverse, unique) ==========" << std::endl;
std::list<int> listA = {1, 2, 3, 4, 5};
std::list<int> listB = {10, 20, 30};
listA.splice(listA.end(), listB);
print_list(listA, "listA after splice");
print_list(listB, "listB (now empty)");
listB = {15, 25, 35};
auto pos = listA.begin();
std::advance(pos, 2);
listA.splice(pos, listB, listB.begin());
print_list(listA, "listA after splice single element");
print_list(listB, "listB (remaining 25,35)");
auto firstB = listB.begin();
auto lastB = listB.end();
listA.splice(listA.end(), listB, firstB, lastB);
print_list(listA, "listA after splice range");
print_list(listB, "listB (now empty)");
std::list<int> unsorted = {5, 2, 8, 1, 9, 3};
print_list(unsorted, "before sort");
unsorted.sort();
print_list(unsorted, "after sort() ascending");
unsorted.sort(std::greater<int>());
print_list(unsorted, "after sort(greater) descending");
unsorted.reverse();
print_list(unsorted, "after reverse (back to ascending)");
std::list<int> dup_list = {1, 1, 2, 3, 3, 3, 4, 2, 2};
print_list(dup_list, "before unique");
dup_list.unique();
print_list(dup_list, "after direct unique (adjacent only)");
dup_list.sort();
dup_list.unique();
print_list(dup_list, "after sort then unique");
std::list<int> merge1 = {1, 3, 5, 7};
std::list<int> merge2 = {2, 4, 6, 8};
merge1.merge(merge2);
print_list(merge1, "merge result merge1");
print_list(merge2, "merge2 (now empty)");
std::list<int> desc1 = {7, 5, 3, 1};
std::list<int> desc2 = {8, 6, 4, 2};
desc1.merge(desc2, std::greater<int>());
print_list(desc1, "merge(greater) descending merge");
std::cout << "\n========== 7. Swap and compare ==========" << std::endl;
std::list<int> swap1 = {1, 2, 3};
std::list<int> swap2 = {4, 5, 6, 7};
print_list(swap1, "swap1 before");
print_list(swap2, "swap2 before");
swap1.swap(swap2);
print_list(swap1, "swap1 after");
print_list(swap2, "swap2 after");
std::list<int> cmp1 = {1, 2, 3};
std::list<int> cmp2 = {1, 2, 3};
std::list<int> cmp3 = {1, 2, 4};
std::cout << std::boolalpha;
std::cout << "cmp1 == cmp2: " << (cmp1 == cmp2) << std::endl;
std::cout << "cmp1 == cmp3: " << (cmp1 == cmp3) << std::endl;
std::cout << "cmp1 < cmp3: " << (cmp1 < cmp3) << std::endl;
std::cout << "\n========== 8. Get allocator ==========" << std::endl;
std::list<int> alloc_list = {10, 20};
auto alloc = alloc_list.get_allocator();
int* p = alloc.allocate(3);
alloc.deallocate(p, 3);
std::cout << "get_allocator example completed" << std::endl;
std::cout << "\n========== 9. Using non-member functions ==========" << std::endl;
const std::list<int> const_list = {100, 200};
auto it_begin = std::begin(const_list);
std::cout << "std::begin value: " << *it_begin << std::endl;
return 0;
}