1 /** 2 * Betterc: Frequently used primitives suitable for use in the BetterC D subset. 3 * inspired by https://theartofmachinery.com/2018/05/27/cpp_classes_in_betterc.html 4 * 5 * Copyright: Maxim Freck, 2018. 6 * Authors: Maxim Freck <maxim@freck.pp.ru> 7 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 8 */ 9 module betterc.cppclass; 10 11 import std.traits: ReturnType; 12 13 /******* 14 * Returns `true` if `T` is destructible with `T.destructor()` method. 15 * In other words tests whether `T` contains `void destructor()` method. 16 * Please note: the parent destructor must be called explicitly. 17 */ 18 enum bool isDestructable(T) = is(ReturnType!((T r) => r.destructor) == void); 19 20 /******* 21 * Creates an instance of T inside the malloc'd memory and calls its constructor. 22 * 23 * Params: 24 * Args... = Constructor arguments 25 * 26 * Returns: an instance of a class of type T 27 */ 28 T cnew(T, Args...)(auto ref Args args) 29 { 30 import core.stdc.stdlib: malloc; 31 import core.stdc.string: memcpy; 32 33 static immutable model = cast(immutable(T)) new T(); 34 enum kTSize = __traits(classInstanceSize, T); 35 auto instance = cast(T)malloc(kTSize); 36 memcpy(cast(void*)instance, cast(void*)model, kTSize); 37 instance.__ctor(args); 38 39 return instance; 40 } 41 42 /******* 43 * Calls the destructor of a previously malloc'd class and frees its memory 44 * 45 * `__xdtor()` is non-virtual and non-@nogc 46 * so let's just use destructor() method 47 * before freing object's memory 48 * 49 * Params: 50 * instance = Class instance 51 */ 52 void cdelete(T)(T instance) 53 { 54 import core.stdc.stdlib: free; 55 56 static if(isDestructable!T) instance.destructor(); 57 free(cast(void*)instance); 58 } 59