Skip to content

Commit f7a2af8

Browse files
committed
Add protected copying functions to @interface
Thanks to Jeroen Van Antwerpen for reminding me that it is possible to have a polymorphic type that is copyable/movable (in fact, I do that a lot in the Cpp2 reflection API), and so it makes sense for an @interface to have _protected_ copying functions - this way the interface is not copyable by default (correct), but a type that implements the interface has the option of defining copy/move if it wants to Made @interface generate protected copy/move construction/assignment Similarly, removed the restriction that @polymorphic_base types cannot be copyable Made operator= "A1" generation work also for polymorphic types - until now it was restricted to only monomorphic types, but it really should work anytime operator= exists - this permits @interface to just define the general operator= as per usual Cpp2 style and get all four functions No change to the "A3" rule, that tends to work great for non-polymorphic types - but while doing this PR I tried applying it also to polymorphic types and noticed it would frequently cause problems in the presence of polymorphic base types, so leaving A3 alone seems useful and right Made the polymorphic reflection API types @copy_constructible instead of @copyable so as not to require generating assignment (they are current inherently non-assignable because some members are not assignable)
1 parent 6fbef64 commit f7a2af8

File tree

10 files changed

+623
-532
lines changed

10 files changed

+623
-532
lines changed
Loading

docs/cpp2/types.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,13 +148,13 @@ As mentioned above:
148148
149149
This graphic summarizes these generalizations. For convenience I've numbered the (A)ssignment and (M)ove defaults.
150150

151-
![image](https://github.com/user-attachments/assets/311f27df-17df-48c4-b0c9-b820afb5be0c)
151+
![image](generalized-copy-move-construction-assignment.png)
152152

153153
In Cpp1 terms, they can be described as follows:
154154

155155
- **(M)ove, M1, M2:** If you write a copy constructor or assignment operator, but not a corresponding move constructor or assignment operator, the latter is generated.
156156

157-
- **(A)ssignment, A1, A3:** If you write a generalized constructor, but none of the three more-specific copy/move constructor/assignment functions, the latter three get generated. If you write a converting copy constructor, but no converting assignment operator for the same type, the latter is generated.
157+
- **(A)ssignment, A1, A3:** If you write a generalized constructor, but none of the three more-specific copy/move constructor/assignment functions, the latter three get generated. If you write a converting copy constructor, but no converting assignment operator for the same type and this is not a polymorphic type, the latter is generated.
158158

159159
- **The arrows are transitive.** For example, if you write a copy constructor and nothing else, the move constructor, copy assignment operator, and move assignment operator are generated.
160160

regression-tests/test-results/pure2-bugfix-for-memberwise-base-assignment.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ class Derived: public Base {
3737

3838
public: explicit Derived();
3939
public: Derived(Derived const& that);
40+
#line 10 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
41+
public: Derived(Derived&& that) noexcept;
4042
public: auto operator=(Derived&& that) noexcept -> Derived& ;
4143
};
4244

@@ -70,6 +72,9 @@ auto main() -> int;
7072
#line 10 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
7173
Derived::Derived(Derived const& that)
7274
: Base{ static_cast<Base const&>(that) }{}
75+
#line 10 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
76+
Derived::Derived(Derived&& that) noexcept
77+
: Base{ static_cast<Base&&>(that) }{}
7378
#line 11 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
7479
auto Derived::operator=(Derived&& that) noexcept -> Derived& {
7580
Base::operator= ( static_cast<Base&&>(that) );

regression-tests/test-results/pure2-print.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ struct values_ret { int offset; std::string name; };
4545
public: explicit mytype();
4646

4747
public: mytype([[maybe_unused]] mytype const& that);
48+
#line 63 "pure2-print.cpp2"
49+
public: auto operator=([[maybe_unused]] mytype const& that) -> mytype& ;
50+
#line 63 "pure2-print.cpp2"
51+
public: mytype([[maybe_unused]] mytype&& that) noexcept;
52+
#line 63 "pure2-print.cpp2"
53+
public: auto operator=([[maybe_unused]] mytype&& that) noexcept -> mytype& ;
4854

4955
public: mytype([[maybe_unused]] cpp2::impl::in<int> unnamed_param_2);
5056

@@ -160,6 +166,14 @@ requires (true) inline CPP2_CONSTEXPR T outer::object_alias{ 42 };
160166

161167
#line 63 "pure2-print.cpp2"
162168
outer::mytype::mytype([[maybe_unused]] mytype const& that){}
169+
#line 63 "pure2-print.cpp2"
170+
auto outer::mytype::operator=([[maybe_unused]] mytype const& that) -> mytype& {
171+
return *this; }
172+
#line 63 "pure2-print.cpp2"
173+
outer::mytype::mytype([[maybe_unused]] mytype&& that) noexcept{}
174+
#line 63 "pure2-print.cpp2"
175+
auto outer::mytype::operator=([[maybe_unused]] mytype&& that) noexcept -> mytype& {
176+
return *this; }
163177

164178
#line 65 "pure2-print.cpp2"
165179
outer::mytype::mytype([[maybe_unused]] cpp2::impl::in<int> unnamed_param_2){}

regression-tests/test-results/pure2-types-inheritance.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,13 @@ class Cyborg;
3030
#line 2 "pure2-types-inheritance.cpp2"
3131
class Human {
3232
public: virtual auto speak() const -> void = 0;
33-
public: virtual ~Human() noexcept;
33+
public: explicit Human();
34+
protected: Human([[maybe_unused]] Human const& that);
3435

35-
public: Human() = default;
36-
public: Human(Human const&) = delete; /* No 'that' constructor, suppress copy */
37-
public: auto operator=(Human const&) -> void = delete;
36+
protected: auto operator=([[maybe_unused]] Human const& that) -> Human& ;
37+
protected: Human([[maybe_unused]] Human&& that) noexcept;
38+
protected: auto operator=([[maybe_unused]] Human&& that) noexcept -> Human& ;
39+
public: virtual ~Human() noexcept;
3840

3941
#line 4 "pure2-types-inheritance.cpp2"
4042
};
@@ -91,6 +93,13 @@ auto main() -> int;
9193
#line 1 "pure2-types-inheritance.cpp2"
9294

9395

96+
Human::Human(){}
97+
Human::Human([[maybe_unused]] Human const& that){}
98+
auto Human::operator=([[maybe_unused]] Human const& that) -> Human& {
99+
return *this;}
100+
Human::Human([[maybe_unused]] Human&& that) noexcept{}
101+
auto Human::operator=([[maybe_unused]] Human&& that) noexcept -> Human& {
102+
return *this;}
94103
Human::~Human() noexcept{}
95104
#line 6 "pure2-types-inheritance.cpp2"
96105
namespace N {

regression-tests/test-results/version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11

2-
cppfront compiler v0.8.2 Build A705:2012
2+
cppfront compiler v0.8.2 Build A706:1407
33
SPDX-License-Identifier Apache-2.0 WITH LLVM-exception
44
Copyright (c) 2022-2024 Herb Sutter

source/build.info

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
"A705:2012"
1+
"A706:1407"

0 commit comments

Comments
 (0)