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 } 334 335 336 @("virtual.base") 337 @safe unittest { 338 shouldCompile( 339 Cpp( 340 q{ 341 class Class { 342 public: 343 virtual void pureVirtualFunc() = 0; 344 virtual void virtualFunc(); 345 void normalFunc(); 346 }; 347 } 348 ), 349 D( 350 q{ 351 static assert(is(Class == class), "Class is not a class"); 352 } 353 ), 354 ); 355 } 356 357 358 @("virtual.child") 359 @safe unittest { 360 shouldCompile( 361 Cpp( 362 q{ 363 class Base { 364 public: 365 virtual void pureVirtualFunc() = 0; 366 virtual void virtualFunc(); 367 void normalFunc(); 368 }; 369 370 class Derived: public Base { 371 public: 372 void pureVirtualFunc() override; 373 }; 374 } 375 ), 376 D( 377 q{ 378 static assert(is(Base == class), "Base is not a class"); 379 static assert(is(Derived == class), "Derived is not a class"); 380 static assert(is(Derived: Base), "Derived is not a child class of Base"); 381 382 auto d = new Derived; 383 d.pureVirtualFunc; 384 } 385 ), 386 ); 387 } 388 389 390 @("virtual.dtor") 391 @safe unittest { 392 shouldCompile( 393 Cpp( 394 q{ 395 class Class { 396 public: 397 virtual ~Class(); 398 }; 399 } 400 ), 401 D( 402 q{ 403 static assert(is(Class == class), "Class is not a class"); 404 } 405 ), 406 ); 407 } 408 409 410 @("virtual.opAssign") 411 @safe unittest { 412 shouldCompile( 413 Cpp( 414 q{ 415 class Class { 416 public: 417 virtual ~Class(); 418 Class& operator=(const Class&); 419 }; 420 } 421 ), 422 D( 423 q{ 424 static assert(is(Class == class), "Class is not a class"); 425 } 426 ), 427 ); 428 } 429 430 431 @("default.ctor") 432 @safe unittest { 433 shouldCompile( 434 Cpp( 435 q{ 436 class Base { 437 public: 438 virtual ~Base(); 439 Base() = default; 440 // the presence of the move ctor caused the compiler to fail with 441 // "cannot implicitly generate a default constructor" 442 // because the default ctor was ignored 443 Base(Base&&) = default; 444 }; 445 446 class Derived: public Base { 447 virtual void func(); 448 }; 449 } 450 ), 451 D( 452 q{ 453 static assert(is(Base == class), "Base is not a class"); 454 static assert(is(Derived == class), "Derived is not a class"); 455 static assert(is(Derived: Base), "Derived is not a child class of Base"); 456 } 457 ), 458 ); 459 }