Skip to content

Commit dced321

Browse files
committed
Make store_as_base<Name,T> follow T's interface, closes #338
`store_as_base<Name, T>` should be echoing `T`s constructor interface: - add a default constructor - guard it and all the constructors with a `requires requires{ T{}; }` clause Also, for a type that doesn't define any constructors, explicitly generate an =default'ed default constructor and =delete copy/move operations
1 parent 5fa2707 commit dced321

File tree

5 files changed

+48
-16
lines changed

5 files changed

+48
-16
lines changed

include/cpp2util.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -647,9 +647,21 @@ class store_as_base
647647
T value;
648648

649649
public:
650-
store_as_base( T const& t ) : value{t} { }
651-
store_as_base( T && t ) : value{std::move(t)} { }
652-
store_as_base( auto && args ) : value{CPP2_FORWARD(args)} { }
650+
store_as_base()
651+
requires requires { T{ }; }
652+
: value{ } { }
653+
654+
store_as_base( T const& t )
655+
requires requires { T{t}; }
656+
: value{t} { }
657+
658+
store_as_base( T && t )
659+
requires requires { T{std::move(t)}; }
660+
: value{std::move(t)} { }
661+
662+
store_as_base( auto && args )
663+
requires requires { T{CPP2_FORWARD(args)}; }
664+
: value{CPP2_FORWARD(args)} { }
653665

654666
auto value__() -> T & { return value; }
655667
auto value__() const -> T const& { return value; }

regression-tests/test-results/pure2-type-and-namespace-aliases.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class myclass {
3030
public: using str = std::string;
3131

3232
private: using str2 = std::string;
33-
};
33+
public: myclass() = default; myclass(myclass const&) = delete; auto operator=(myclass const&) -> void = delete; };
3434

3535
namespace N3 = ::std::literals;
3636

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class myclass {
5353

5454
public: class nested {
5555
public: static auto g() -> void;
56-
};
56+
public: nested() = default; nested(nested const&) = delete; auto operator=(nested const&) -> void = delete; };
5757

5858
public: template<typename T, typename U> [[nodiscard]] static auto f1(T const& t, U const& u) -> auto;
5959
public: template<typename T, typename U> [[nodiscard]] static auto f2(T const& t, U const& u) -> auto;

regression-tests/test-results/pure2-types-order-independence-and-nesting.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ namespace M {
6969
template<typename T, typename U> class A {
7070
public: template<int I> class B {
7171
public: template<typename V, int J, typename W> static auto f(W const& w) -> void;
72-
};
73-
};
72+
public: B() = default; B(B const&) = delete; auto operator=(B const&) -> void = delete; };
73+
public: A() = default; A(A const&) = delete; auto operator=(A const&) -> void = delete; };
7474

7575
}
7676

source/cppfront.cpp

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4898,8 +4898,9 @@ class cppfront
48984898

48994899
// Type definition
49004900

4901-
auto separator = std::string{":"};
4902-
auto started_body = false;
4901+
auto separator = std::string{":"};
4902+
auto started_body = false;
4903+
auto found_constructor = false;
49034904
assert(compound_stmt);
49044905

49054906
for (auto& stmt : compound_stmt->statements)
@@ -4916,6 +4917,10 @@ class cppfront
49164917
auto& decl = std::get<statement_node::declaration>(stmt->statement);
49174918
assert(decl);
49184919

4920+
if (decl->is_constructor()) {
4921+
found_constructor = true;
4922+
}
4923+
49194924
// First we'll encounter the base types == subobjects named "this"
49204925
// and any data members declared before them that we push into private bases
49214926
assert(decl->name());
@@ -4959,15 +4964,30 @@ class cppfront
49594964
}
49604965

49614966
// Ensure we emit the { even if there are only bases in the type
4962-
if (
4963-
printer.get_phase() == printer.phase1_type_defs_func_decls
4964-
&& !started_body
4965-
)
4967+
if (printer.get_phase() == printer.phase1_type_defs_func_decls)
49664968
{
4967-
printer.print_cpp2(" {", compound_stmt->position());
4968-
}
4969+
if (!started_body) {
4970+
printer.print_cpp2(" {", compound_stmt->position());
4971+
}
4972+
4973+
// If there no constructor was defined, there shoudl only be
4974+
// a default constructor, so generate that and disable copy/move
4975+
if (!found_constructor) {
4976+
auto id = print_to_string(*n.identifier);
4977+
printer.print_cpp2(
4978+
"public: " + id + "() = default; ",
4979+
compound_stmt->position()
4980+
);
4981+
printer.print_cpp2(
4982+
"" + id + "(" + id + " const&) = delete; ",
4983+
compound_stmt->position()
4984+
);
4985+
printer.print_cpp2(
4986+
"auto operator=(" + id + " const&) -> void = delete; ",
4987+
compound_stmt->position()
4988+
);
4989+
}
49694990

4970-
if (printer.get_phase() == printer.phase1_type_defs_func_decls) {
49714991
printer.print_cpp2("};\n", compound_stmt->close_brace);
49724992
}
49734993
}

0 commit comments

Comments
 (0)