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