I never used Catch, so I can not imagine a working example.
However, I do unit test classes with complex copy / move constructors (e.g. using deep copies, std::unique_ptr , etc.) by testing class methods on moved / copied objects.
For example, if I have a class as follows:
// constructor Foo::Foo(int i) : privateMember(i) {}; // some function that operates on this private member int Foo::bar() { return privateMember + 5 };
I will have a test for the bar() method, but then duplicate it for the move, copy, etc. constructors. You can easily complete the original tests three or four times.
I do not expose member variables. If you do, you can use the "same" test functions (assuming Catch supports this). For example, make sure that a deep copy creates a unique copy (i.e. does not point to the original object).
Update
You seem to be more worried about the correct constructor / assignment of move or copy being called. If you just want to โmove destinationโ or some other identifier, I donโt know what to offer.
When I test the copy, I am sure that I am copying the object to my unit test and then calling functions that depend on shallow / deep copies of the member variables. This is the same when I test the movement. In some scenarios, you can run tests on the source object (for example, check that the vector instance variable now has a size of zero after moving).
I force the move constructor as follows:
Foo foo(); Foo bar(std::move(foo));
I force the move destination as follows:
Foo foo(); Foo bar(); bar = std::move(foo);
I force the copy constructor as follows:
Foo foo(); Foo bar(foo);
I force the copy as follows:
Foo foo(); Foo bar(); bar = foo;
If you really need it, you can inherit from some debugging virtual class that provides an enum class field. In your debug assembly, the field is populated with the corresponding enumeration value (MoveConstructor). This field is open, so you can check it after copying / moving. Make sure you populate it in your copy and move constructor constructs.