Is the default move constructor an optimized compiler?
I have a std :: multimap of the following type:
typedef std::multimap<std::pair<bool,uint32_t>, FooObject>
FooObject has a default move copy and declares the declared constructors:
FooObject(FooObject&& v) = default;
FooObject& operator=(FooObject&& other)=default;
The copy / assign constructors are private to disable implicit copy.
So, I should be able to insert a pair into a card like this:
mymap.emplace(std::make_pair(false,32),FooObject());
This displays a list of errors with a number at the end:
error C2660: 'std :: pair :: pair': function does not take 2 arguments
If I declare copy destination constructors without default, then it compiles fine.
FooObject(FooObject&& v){}
FooObject& operator=(FooObject&& other){}
Why? Does the compiler optimize these constructors when marked with the "default" keyword? I am using MSVC140
UPDATE:
Based on the comments below, I found the reason - FooObject has a non-copyable instance. Here is the FooObject:
#define NO_COPY_ASSIGN(TypeName) \
TypeName (const TypeName &); \
void operator= (const TypeName &);
class FooObject
{
private:
NO_COPY_ASSIGN(FooObject)
public:
struct FooStruct
{
FooBuffer frameBuffer; //<--Here it is
}fooStruct;
FooObject(){}
/** Move constructor to allow insert into vector without copy */
FooObject(FooObject&& v) = default;
FooObject& operator=(FooObject&& other) = default;
};
* FooBuffer also has its own copy / assignment private. But I still don't understand why to replace "default" with {} fixes. Explain, please.
source to share
Difference between
FooObject(FooObject&& v) = default;
and
FooObject(FooObject&& v){}
This is that the former will emit a constructor that moves each element from v
, and the latter by default builds each element and does nothing with v
.
Since it FooBuffer
does not move, it means that the compiler will delete FooObject(FooObject&& v) = default;
as it will be ill-formed.
With FooObject(FooObject&& v){}
you, you don't have this problem, since you never try to move items v
. Since there is no member initialization list, the compiler will add one for you, which only creates members by default.
You can see this behavior more clearly with this:
struct Moveable
{
Moveable() = default;
Moveable(Moveable&&) { std::cout << "in Moveable(Moveable&&)\n"; }
};
struct Foo
{
Foo() = default;
Foo(Foo&&) = default;
Moveable m;
};
struct Bar
{
Bar() = default;
Bar(Bar&&){}
Moveable m;
};
int main()
{
Foo f;
Bar b;
std::cout << "test_f\n";
Foo test_f(std::move(f));
std::cout << "test_b\n";
Bar test_b(std::move(b));
}
which outputs
test_f
in Moveable(Moveable&&)
test_b
Indicates that Bar
nothing is being moved in the move constructor .
source to share
Your problem is that one of the members is FooObject
unable to move, which prevents the compiler from generating default move operations.
The versions of the move operations you {}
perform do not (in particular: they do not actually perform the move operation) on members FooObject
and are therefore legal.
source to share