p11.0x.move.cpp
6.98 KB
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
struct Trivial {};
struct NonTrivial {
NonTrivial(NonTrivial&&); // expected-note{{copy constructor is implicitly deleted}}
};
struct DeletedCopy {
DeletedCopy(const DeletedCopy&) = delete;
};
// A defaulted move constructor for a class X is defined as deleted if X has:
// -- a variant member with a non-trivial corresponding constructor
union DeletedNTVariant {
NonTrivial NT; // expected-note{{deleted because variant field 'NT' has a non-trivial move constructor}}
DeletedNTVariant(DeletedNTVariant&&);
};
DeletedNTVariant::DeletedNTVariant(DeletedNTVariant&&) = default; // expected-error{{would delete}}
struct DeletedNTVariant2 {
union {
NonTrivial NT; // expected-note{{deleted because variant field 'NT' has a non-trivial move constructor}}
};
DeletedNTVariant2(DeletedNTVariant2&&);
};
DeletedNTVariant2::DeletedNTVariant2(DeletedNTVariant2&&) = default; // expected-error{{would delete}}
// Note, move constructor is not a candidate because it is deleted.
template<typename T> struct DeletedNTVariant3 { // expected-note 2{{default}} expected-note 2{{copy}}
union {
T NT;
};
};
extern DeletedNTVariant3<NonTrivial> dntv3a(0); // expected-error {{no matching}}
extern DeletedNTVariant3<DeletedCopy> dntv3a(0); // expected-error {{no matching}}
// -- a non-static data member of class type M (or array thereof) that cannot be
// copied because overload resolution results in an ambiguity or a function
// that is deleted or inaccessible
struct NoAccess {
NoAccess() = default;
private:
NoAccess(NoAccess&&);
friend struct HasAccess;
};
struct HasNoAccess {
NoAccess NA; // expected-note{{deleted because field 'NA' has an inaccessible move constructor}}
HasNoAccess(HasNoAccess&&);
};
HasNoAccess::HasNoAccess(HasNoAccess&&) = default; // expected-error{{would delete}}
struct HasAccess {
NoAccess NA;
HasAccess(HasAccess&&);
};
HasAccess::HasAccess(HasAccess&&) = default;
struct Ambiguity {
Ambiguity(const Ambiguity&&);
Ambiguity(volatile Ambiguity&&);
};
struct IsAmbiguous {
Ambiguity A; // expected-note{{deleted because field 'A' has multiple move constructors}}
IsAmbiguous(IsAmbiguous&&); // expected-note{{copy constructor is implicitly deleted because 'IsAmbiguous' has a user-declared move constructor}}
};
IsAmbiguous::IsAmbiguous(IsAmbiguous&&) = default; // expected-error{{would delete}}
struct Deleted {
// FIXME: This diagnostic is slightly wrong: the constructor we select to move
// 'IA' is deleted, but we select the copy constructor (we ignore the move
// constructor, because it was defaulted and deleted).
IsAmbiguous IA; // expected-note{{deleted because field 'IA' has a deleted move constructor}}
Deleted(Deleted&&);
};
Deleted::Deleted(Deleted&&) = default; // expected-error{{would delete}}
// It's implied (but not stated) that this should also happen if overload
// resolution fails.
struct ConstMember {
const Trivial ct;
ConstMember(ConstMember&&);
};
ConstMember::ConstMember(ConstMember&&) = default; // ok, calls copy ctor
struct ConstMoveOnlyMember {
// FIXME: This diagnostic is slightly wrong: the constructor we select to move
// 'cnt' is deleted, but we select the copy constructor, because the object is
// const.
const NonTrivial cnt; // expected-note{{deleted because field 'cnt' has a deleted move constructor}}
ConstMoveOnlyMember(ConstMoveOnlyMember&&);
};
ConstMoveOnlyMember::ConstMoveOnlyMember(ConstMoveOnlyMember&&) = default; // expected-error{{would delete}}
struct VolatileMember {
volatile Trivial vt; // expected-note{{deleted because field 'vt' has no move constructor}}
VolatileMember(VolatileMember&&);
};
VolatileMember::VolatileMember(VolatileMember&&) = default; // expected-error{{would delete}}
// -- a direct or virtual base class B that cannot be moved because overload
// resolution results in an ambiguity or a function that is deleted or
// inaccessible
struct AmbiguousMoveBase : Ambiguity { // expected-note{{deleted because base class 'Ambiguity' has multiple move constructors}}
AmbiguousMoveBase(AmbiguousMoveBase&&); // expected-note{{copy constructor is implicitly deleted}}
};
AmbiguousMoveBase::AmbiguousMoveBase(AmbiguousMoveBase&&) = default; // expected-error{{would delete}}
struct DeletedMoveBase : AmbiguousMoveBase { // expected-note{{deleted because base class 'AmbiguousMoveBase' has a deleted move constructor}}
DeletedMoveBase(DeletedMoveBase&&);
};
DeletedMoveBase::DeletedMoveBase(DeletedMoveBase&&) = default; // expected-error{{would delete}}
struct InaccessibleMoveBase : NoAccess { // expected-note{{deleted because base class 'NoAccess' has an inaccessible move constructor}}
InaccessibleMoveBase(InaccessibleMoveBase&&);
};
InaccessibleMoveBase::InaccessibleMoveBase(InaccessibleMoveBase&&) = default; // expected-error{{would delete}}
// -- any direct or virtual base class or non-static data member of a type with
// a destructor that is deleted or inaccessible
struct NoAccessDtor {
NoAccessDtor(NoAccessDtor&&); // expected-note{{copy constructor is implicitly deleted because 'NoAccessDtor' has a user-declared move constructor}}
private:
~NoAccessDtor();
friend struct HasAccessDtor;
};
struct HasNoAccessDtor {
NoAccessDtor NAD; // expected-note {{deleted because field 'NAD' has an inaccessible destructor}}
HasNoAccessDtor(HasNoAccessDtor&&);
};
HasNoAccessDtor::HasNoAccessDtor(HasNoAccessDtor&&) = default; // expected-error{{would delete}}
struct HasAccessDtor {
NoAccessDtor NAD;
HasAccessDtor(HasAccessDtor&&);
};
HasAccessDtor::HasAccessDtor(HasAccessDtor&&) = default;
struct HasNoAccessDtorBase : NoAccessDtor { // expected-note{{copy constructor of 'HasNoAccessDtorBase' is implicitly deleted because base class 'NoAccessDtor' has a deleted copy constructor}}
};
extern HasNoAccessDtorBase HNADBa;
HasNoAccessDtorBase HNADBb(HNADBa); // expected-error{{implicitly-deleted copy constructor}}
// The restriction on rvalue reference members applies to only the copy
// constructor.
struct RValue {
int &&ri = 1;
RValue(RValue&&);
};
RValue::RValue(RValue&&) = default;
// -- a non-static data member or direct or virtual base class with a type that
// does not have a move constructor and is not trivially copyable
struct CopyOnly {
CopyOnly(const CopyOnly&);
};
struct NonMove {
CopyOnly CO;
NonMove(NonMove&&);
};
NonMove::NonMove(NonMove&&) = default; // ok under DR1402
struct Moveable {
Moveable();
Moveable(Moveable&&);
};
struct HasMove {
Moveable M;
HasMove(HasMove&&);
};
HasMove::HasMove(HasMove&&) = default;
namespace DR1402 {
struct member {
member();
member(const member&);
member& operator=(const member&);
~member();
};
struct A {
member m_;
A() = default;
A(const A&) = default;
A& operator=(const A&) = default;
A(A&&) = default;
A& operator=(A&&) = default;
~A() = default;
};
// ok, A's explicitly-defaulted move operations copy m_.
void f() {
A a, b(a), c(static_cast<A&&>(a));
a = b;
b = static_cast<A&&>(c);
}
}