已声明默认移动赋值运算符但std::is_move_assignable_v仍为false的问题
Let's break down your problem and address each part clearly:
Why std::is_move_assignable_v<DLXMatrix> Returns False
The root cause lies in a combination of C++ standard rules and your redundant operator declarations:
- Custom copy constructor suppresses default move operations: When you declare a custom copy constructor (
DLXMatrix(const DLXMatrix &);), the C++ standard mandates that implicit move assignment operators are deleted. Even if you explicitly writeoperator=(DLXMatrix&&) = default;, older C17 compilers like g 7.5.0 and clang++ 6.0.0 will still treat this defaulted operator as deleted due to the presence of your custom copy constructor. - Overload resolution conflict: When you attempt
t = std::move(t2), the compiler prioritizes theoperator=(DLXMatrix&&)overload (even though it's deleted) over youroperator=(DLXMatrix other)copy-and-swap operator. This makes the move assignment expression invalid, hencestd::is_move_assignable_v<DLXMatrix>evaluates to false.
Is Your Core Implementation Reasonable?
Yes, your core design is sound:
- You correctly avoided default copy operations because
Headerpointers reference elements within the samestd::vector, which would become dangling if you copied the vector naively. - Ensuring the vector never resizes or moves memory is a smart choice—it prevents pointer invalidation during the object's lifetime.
- Defaulting the move constructor is safe: moving the vector transfers ownership of its underlying buffer, so the
Headerpointers in the new object still reference valid elements in the moved vector. - The default destructor is safe: the vector handles memory cleanup automatically, and
Headerpointers don't manage dynamic memory, so no leaks occur.
Fixes to Resolve the Issues
You have two clean options to fix the move assignability problem:
Option 1: Remove the Redundant Move Assignment Operator
Your operator=(DLXMatrix other) (copy-and-swap style) already handles both copy and move assignments efficiently. When passed a right value, other is constructed via the move constructor, then swapped into place—this is just as efficient as a dedicated move assignment operator.
Update your class declaration by removing this line:
DLXMatrix &operator=(DLXMatrix &&other) = default;
This will:
- Make
std::is_move_assignable_v<DLXMatrix>evaluate to true, sincet = std::move(t2)will now resolve to your copy-and-swap operator. - Fix
std::swapcompilation, as swap relies on valid move operations.
Option 2: Implement a Custom Move Assignment Operator
If you want a dedicated move assignment operator (for clarity or edge cases), don't use = default;—implement it explicitly:
DLXMatrix &operator=(DLXMatrix &&other) noexcept { if (this != &other) { heads = std::move(other.heads); // No need to adjust pointers: moving the vector transfers its buffer, // so all pointers still reference valid elements in the new vector } return *this; }
This ensures the move assignment operator is valid, resolves overload resolution correctly, and maintains the efficiency of transferring vector ownership.
内容的提问来源于stack exchange,提问作者hivert

