In the latest update of C++ to version C++17 there was some things which were changed, for example, the constructor of std::pair<int, const std::unique_ptr<int>>
from an rvalue of type std::pair<int, std::unique_ptr<int>>
is explicit
in C++14, and implicit and C++17.
Note that this behavior was only seen in libstdc++ and libc++ libraries. In MSVC’s library, the constructor is always implicit.
This article will discuss why the move constructor was explicit
in C++14 and why it was changed in C++17.
Detailed reason to understand why the move constructor is not explicit anymore in the latest version of C++ that is C++17 is given below:
Why the move constructor is not explicit anymore in C++17?
For a short explanation, you should know that the return statement from the move constructor copy-initializes the A
return value from the operand and before C++17, but in C++ 17 version mandatory copy elision applies and the copy-initialization does not contain the direct-initialization via the move constructor anymore.
To understand why the move constructor is not explicit anymore in C++17, you need to know that the relevant constructors have not been explicit
before C++17 either.
For example, the GCC and Clang in before the C++17 version was launched, are actually considering std::is_convertible<B, A>::value
false because A
‘s ‘move’ constructor is implicitly deleted.
The move constructor is implicitly deleted, because a const std::unique_ptr
cannot be moved or copied in the code.
The move constructor is required to fulfill the following command std::is_convertible<B, A>::value
before C++17, because it tests whether a function of the form, given below, would be well-formed:
A test() {
return std::declval<B>();
}
The return statement copy-initializes the A
return value from the operand and before C++17, copy-initialization always involved a conversion to a temporary of the target type if necessary, then followed by direct-initialization of the target from the temporary.
That direct-initialization would use the move constructor of A
. The move can be elided by the compiler, but the move constructor must still be usable.
Since the C++17 compulsory copy elision applies and even conceptually, the copy-initialization does not contain the direct-initialization via the move constructor anymore.
This is the reason why the move constructor is not explicit anymore in the latest version of C++ that is C++17
Conclusion
To understand ‘Why the move constructor is not explicit anymore in C++17’ a short explanation would be,you should know that the return statement from the move constructor copy-initializes the A
return value from the operand and before C++17.
But now in C++17 mandatory copy elision applies and the copy-initialization does not contain the direct-initialization via the move constructor anymore.