> Should the Move Constructor also be noexcept?
It makes no difference. The move constructor of
Test
is declared as defaulted;
std::unique_ptr<>
is nothrow move constructible; therefore the defaulted move constructor of
Test
is implicitly
noexcept
The move assignment operator of
Test
is not declared as defaulted , and an explict
noexcept
is required.
Declaring explicitly deleted copy constructor and copy assignment for
Test
also makes no difference.
std::unique_ptr<>
is not copy constructible or copy assignable; these would have been implicitly deleted.
In the following snippet,
A
,
B
and
C
are all equivalent as far as the foundation operations are concerned:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
|
#include <memory>
#include <type_traits>
#include <iostream>
struct A
{
A() ;
// copy constructor and copy assignment are implicitly deleted
// move constructor is declared as defaulted
A( A&& ) noexcept = default ;
A& operator=( A&& ) noexcept ;
~A() noexcept ;
private:
struct opaque ;
std::unique_ptr<opaque> implementation ;
};
struct B
{
B() ;
// copy constructor and copy assignment are implicitly deleted
// move constructor is declared as defaulted;
// the defaulted move constructor is implicitly noexcept
B( B&& ) = default ;
B& operator=( B&& ) noexcept ;
~B() noexcept ;
private:
struct opaque ;
std::unique_ptr<opaque> implementation ;
};
struct C
{
C() ;
// copy constructor and copy assignment are explicity deleted
C( C& ) = delete ;
C& operator=( C& ) = delete ;
// move constructor is declared as defaulted
C( C&& ) noexcept = default ;
C& operator=( C&& ) noexcept ;
~C() noexcept ;
private:
struct opaque ;
std::unique_ptr<opaque> implementation ;
};
int main()
{
std::cout << std::boolalpha << "A - \n "
<< std::is_copy_constructible<A>::value << "\n " // false
<< std::is_copy_assignable<A>::value << "\n " // false
<< std::is_nothrow_move_constructible<A>::value << "\n " // true
<< std::is_nothrow_move_assignable<A>::value << '\n' ; // true
std::cout << "\nB - \n "
<< std::is_copy_constructible<B>::value << "\n " // false
<< std::is_copy_assignable<B>::value << "\n " // false
<< std::is_nothrow_move_constructible<B>::value << "\n " // true
<< std::is_nothrow_move_assignable<B>::value << '\n' ; // true
std::cout << "\nC - \n "
<< std::is_copy_constructible<C>::value << "\n " // false
<< std::is_copy_assignable<C>::value << "\n " // false
<< std::is_nothrow_move_constructible<C>::value << "\n " // true
<< std::is_nothrow_move_assignable<C>::value << '\n' ; // true
}
|