diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index f92ffae9..06191ed6 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -958,7 +958,18 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE { this->copy_construct_impl(other.controller); } - inline constexpr deque &operator=(deque const &) = delete; + inline constexpr deque &operator=(deque const &other) noexcept(::std::is_nothrow_copy_constructible_v) + { + if (__builtin_addressof(other) == this) + { + return *this; + } + deque temp(other); + destroy_deque_controller(this->controller); + this->controller = temp.controller; + temp.controller = {{}, {}, {}}; + return *this; + } inline constexpr deque(deque &&other) noexcept : controller(other.controller) { diff --git a/tests/0026.container/0003.deque/constructors/copy_assignment.cc b/tests/0026.container/0003.deque/constructors/copy_assignment.cc new file mode 100644 index 00000000..7df96c3b --- /dev/null +++ b/tests/0026.container/0003.deque/constructors/copy_assignment.cc @@ -0,0 +1,141 @@ +#include +#include +#include + +template +inline void test_copy_assignment() +{ + ::fast_io::io::perr("=== copy assignment test ===\n"); + + // Build source deque + ::fast_io::deque src; + for (::std::size_t i{}; i != 4096u; ++i) + { + if constexpr (::std::same_as) + { + src.push_back(i); + } + else + { + src.push_back(::fast_io::string(::fast_io::concat_fast_io(i))); + } + } + + // Build destination deque with garbage data + ::fast_io::deque dst; + for (::std::size_t i{}; i != 1234u; ++i) + { + if constexpr (::std::same_as) + { + dst.push_back(999999u); + } + else + { + dst.emplace_back("garbage"); + } + } + + // Perform copy assignment + dst = src; + + // Check size + if (dst.size() != src.size()) + { + ::fast_io::io::panic("ERROR: dst.size() != src.size() after copy assignment\n"); + } + + // Check element equality + ::std::size_t idx{}; + for (T const &e : dst) + { + if constexpr (::std::same_as) + { + if (e != idx) + { + ::fast_io::io::panicln("ERROR: dst element mismatch: ", e); + } + } + else + { + ::fast_io::string expected(::fast_io::concat_fast_io(idx)); + if (e != expected) + { + ::fast_io::io::panicln("ERROR: dst string mismatch: ", e); + } + } + ++idx; + } + + // Modify src to ensure deep copy + if constexpr (::std::same_as) + { + for (::std::size_t i{}; i != src.size(); ++i) + { + src[i] = src[i] + 1u; + } + } + else + { + for (::std::size_t i{}; i != src.size(); ++i) + { + src[i].append("_changed"); + } + } + + // dst must remain unchanged + idx = 0u; + for (T const &e : dst) + { + if constexpr (::std::same_as) + { + if (e != idx) + { + ::fast_io::io::panicln("ERROR: dst changed after modifying src: ", e); + } + } + else + { + ::fast_io::string expected(::fast_io::concat_fast_io(idx)); + if (e != expected) + { + ::fast_io::io::panicln("ERROR: dst string changed after modifying src: ", e); + } + } + ++idx; + } + + // Self-assignment test + dst = dst; + + // Verify unchanged after self-assignment + idx = 0u; + for (T const &e : dst) + { + if constexpr (::std::same_as) + { + if (e != idx) + { + ::fast_io::io::panicln("ERROR: dst changed after self-assignment: ", e); + } + } + else + { + ::fast_io::string expected(::fast_io::concat_fast_io(idx)); + if (e != expected) + { + ::fast_io::io::panicln("ERROR: dst string changed after self-assignment: ", e); + } + } + ++idx; + } + + ::fast_io::io::print("copy assignment test finished\n"); +} + +int main() +{ + test_copy_assignment<::std::size_t>(); + test_copy_assignment<::fast_io::string>(); + + ::fast_io::io::print("All copy assignment tests finished\n"); +}