1 module it.cpp.class_;
2 
3 import it;
4 
5 @("POD struct")
6 @safe unittest {
7     shouldCompile(
8         Cpp(
9             q{
10                 struct Foo { int i; double d; };
11             }
12         ),
13         D(
14             q{
15                 auto f = Foo(42, 33.3);
16                 static assert(is(Foo == struct), "Foo should be a struct");
17                 f.i = 7;
18                 f.d = 3.14;
19             }
20         ),
21    );
22 }
23 
24 @("POD struct private then public")
25 @safe unittest {
26     shouldCompile(
27         Cpp(
28             q{
29                 struct Foo {
30                 private:
31                     int i;
32                 public:
33                     double d;
34                 };
35             }
36         ),
37         D(
38             q{
39                 static assert(is(Foo == struct), "Foo should be a struct");
40                 static assert(__traits(getProtection, __traits(getMember, Foo, "i")) == "private");
41                 static assert(__traits(getProtection, __traits(getMember, Foo, "d")) == "public");
42                 Foo f;
43                 f.d = 22.2;
44             }
45         ),
46    );
47 }
48 
49 
50 @("POD class")
51 @safe unittest {
52     shouldCompile(
53         Cpp(
54             q{
55                 class Foo { int i; double d; };
56             }
57         ),
58         D(
59             q{
60                 static assert(is(Foo == struct), "Foo should be a struct");
61                 static assert(__traits(getProtection, __traits(getMember, Foo, "i")) == "private");
62                 static assert(__traits(getProtection, __traits(getMember, Foo, "d")) == "private");
63             }
64         ),
65    );
66 }
67 
68 @("POD class public then private")
69 @safe unittest {
70     shouldCompile(
71         Cpp(
72             q{
73                 class Foo {
74                 public:
75                     int i;
76                 private:
77                     double d;
78                 };
79             }
80         ),
81         D(
82             q{
83                 static assert(is(Foo == struct), "Foo should be a struct");
84                 static assert(__traits(getProtection, __traits(getMember, Foo, "i")) == "public");
85                 static assert(__traits(getProtection, __traits(getMember, Foo, "d")) == "private");
86                 Foo f;
87                 f.i = 7; // public, ok
88             }
89         ),
90    );
91 }
92 
93 
94 @("struct method")
95 @safe unittest {
96     shouldCompile(
97         Cpp(
98             q{
99                 struct Adder {
100                     int add(int i, int j);
101                 };
102             }
103         ),
104         D(
105             q{
106                 static assert(is(Adder == struct), "Adder should be a struct");
107                 auto adder = Adder();
108                 int i = adder.add(2, 3);
109             }
110         ),
111    );
112 }
113 
114 @("ctor")
115 @safe unittest {
116     shouldCompile(
117         Cpp(
118             q{
119                 struct Adder {
120                     int i;
121                     Adder(int i, int j);
122                     int add(int j);
123                 };
124             }
125         ),
126         D(
127             q{
128                 static assert(is(Adder == struct), "Adder should be a struct");
129                 auto adder = Adder(1, 2);
130                 int i = adder.add(4);
131             }
132         ),
133    );
134 }
135 
136 @("const method")
137 @safe unittest {
138     shouldCompile(
139         Cpp(
140             q{
141                 struct Adder {
142                     int i;
143                     Adder(int i, int j);
144                     int add(int j) const;
145                 };
146             }
147         ),
148         D(
149             q{
150                 static assert(is(Adder == struct), "Adder should be a struct");
151                 auto adder = const Adder(1, 2);
152                 int i = adder.add(4);
153             }
154         ),
155    );
156 }
157 
158 
159 @("inheritance.struct.single")
160 @safe unittest {
161     shouldCompile(
162         Cpp(
163             q{
164                 struct Base {
165                     int i;
166                 };
167 
168                 struct Derived: public Base {
169                     double d;
170                 };
171             }
172         ),
173         D(
174             q{
175                 static assert(is(typeof(Derived.i) == int));
176                 static assert(is(typeof(Derived.d) == double));
177             }
178         ),
179    );
180 }
181 
182 
183 @("inheritance.struct.multiple")
184 @safe unittest {
185     shouldCompile(
186         Cpp(
187             q{
188                 struct Base0 {
189                     int i;
190                 };
191 
192                 struct Base1 {
193                     double d;
194                 };
195 
196                 struct Derived: public Base0, public Base1 {
197 
198                 };
199             }
200         ),
201         D(
202             q{
203                 static assert(is(typeof(Derived.i) == int));
204                 static assert(is(typeof(Derived._base1.d) == double));
205             }
206         ),
207    );
208 }
209 
210 
211 @("hard_to_describe")
212 @safe unittest {
213     shouldCompile(
214         Cpp(
215             q{
216                 struct Member {
217                     // having a constructor caused dpp to emit a `@disable this`
218                     Member(const char*);
219                 };
220 
221                 template <typename T>
222                 struct Template {
223                     T payload;
224                 };
225 
226                 struct Struct {
227                     Member member;
228                     static Template<Struct> global;
229                 };
230             }
231         ),
232         D(
233             q{
234                 // just to check that the D code compiles
235             }
236         ),
237    );
238 }
239 
240 
241 @("rule_of_5")
242 @safe unittest {
243     shouldCompile(
244         Cpp(
245             q{
246                 struct Struct {
247                     Struct(Struct&&) = default;
248                     Struct& operator=(Struct&&) = default;
249                     Struct& operator=(const Struct&) = default;
250                 };
251             }
252         ),
253         D(
254             q{
255                 // just to check that the D code compiles
256             }
257         ),
258    );
259 }
260 
261 
262 @("inner.return.nons")
263 @safe unittest {
264     shouldCompile(
265         Cpp(
266             q{
267                 struct Struct {
268                     template<typename V>
269                     struct Inner {};
270                 };
271                 const Struct::Inner<int>& inners();
272             }
273         ),
274         D(
275             q{
276                 // just to check that the D code compiles
277             }
278         ),
279    );
280 }
281 
282 
283 @("inner.return.ns.normal")
284 @safe unittest {
285     shouldCompile(
286         Cpp(
287             q{
288                 // it's important to have two different namespaces
289                 namespace lens0 {
290                     struct Struct {
291                         template<typename V>
292                         struct Inner {};
293                     };
294                 }
295 
296                 const lens0::Struct::Inner<int>& inners();
297             }
298         ),
299         D(
300             q{
301                 // just to check that the D code compiles
302             }
303         ),
304    );
305 }
306 
307 
308 @("inner.return.ns.using")
309 @safe unittest {
310     shouldCompile(
311         Cpp(
312             q{
313                 // it's important to have two different namespaces
314                 namespace lens0 {
315                     struct Struct {
316                         template<typename V>
317                         struct Inner {};
318                     };
319                 }
320 
321                 namespace lens1 {
322                     using namespace lens0;
323                     const Struct::Inner<int>& inners();
324                 }
325             }
326         ),
327         D(
328             q{
329                 // just to check that the D code compiles
330             }
331         ),
332    );
333 }