Reputation: 2025
#include <utility>
struct A {};
struct B {
B(A&&) {}
B(const B&) = delete;
};
static void func(B) {}
int main() {
A a;
func(std::move(a));
}
This program is accepted by:
-std=c++17
-std=c++17
Was the standard changed regarding this in C++17? Is MSVC wrong in accepting this before C++17?
Upvotes: 3
Views: 63
Reputation: 172954
MSVC is wrong. For guaranted copy elision since C++17,
The objects are constructed directly into the storage where they would otherwise be copied/moved to. The copy/move constructors need not be present or accessible:
- In the initialization of an object, when the initializer expression is a prvalue of the same class type (ignoring cv-qualification) as the variable type:
Given func(std::move(a));
, std::move(a)
is used to construct a temporary B
via B::B(A&&)
firstly, then the temporary is copied as the parameter to func
via B::B(const B&)
. The copy operation is omitted at all, the parameter is constructed from std::move(a)
directly via B::B(A&&)
.
Before C++17, this is an optimization, the copy/move constructor still must be present and accessible.
Upvotes: 4