Description:
The defaulted move-assignment operator for scoped_connection overwrites m_conn without first calling disconnect(). The old callback remains registered in the signal and keeps firing — violating the RAII contract.
Additionally, scoped_connection lacks a default constructor, making move-assignment impractical since there's no way to create an empty instance to later assign into (e.g. as a class member).
This PR:
- Replaces the defaulted move-assignment with a custom one that disconnects the old connection before moving.
- Adds a default constructor, enabling the member-variable pattern:
struct Wallet { btcsignals::scoped_connection m_conn; // m_conn can be move-assigned later };
Reproduction (before fix):
btcsignals::scoped_connection sc0 = sig.connect(IncrementCallback);
btcsignals::scoped_connection sc1 = sig.connect(SquareCallback);
sc0 = std::move(sc1);
val = 3; sig(val);
// Expected: 9 (only SquareCallback)
// Actual: 16 (both callbacks fire, old connection leaked)
Testing:
Added scoped_connection_move_assignment test covering default construction, move-assignment disconnect behavior, and self-move-assignment safety. Test fails on master (16 != 9), passes with this change.