Attention, C and C++ programmers are more likely to use what I'm going to talk about.

If you're a C++ programmer, you're probably thinking about shared/unique pointers. But that's not what this is about.

Take the `void*` type. This type can be pretty much anything, this is "okay" if you wanted to make your code more generic, but there is a much better way to handle that. Look at that code:

```d
import core.stdc.stdlib;
void* myInt = malloc(int.sizeof);
*(cast(int*)myInt) = 500;
writeln(*(cast(int*)myInt));
free(myInt);
```

This is a code that can be common to happen on C, but you can do it a lot better. You can actually make your casting a bit saving information about its size, you could do it with a struct, but you could also do it with one of the D features: slicing:
```d
import core.stdc.stdlib;
void[] myInt = malloc(int.sizeof)[0..int.sizeof);
```
Now, you will have information saved on how much info is allocated on your int by doing `myInt.length`. Which means that any attempt to assign data to the pointed location, this location will be bound checked.


Another thing I strongly recommend is not using malloc. The first reason is that it makes your code harder to read, unsafe, untraceable and longer.
If you just use instead:

```d
void[] myInt = new void[int.sizeof];
```

Will basically have the same effect of the code before in terms of usage, no import, less to write, traceable code (-profile=gc).

Now, if you need to use that just for the sake of generic data and no heap allocation is really needed, I must recall on your mind the underused `union` and the underused `std.variant` (aka Tagged Union). My own way to use union if you don't need the tagged union as you already know how your data flow works, this is a pattern that I shall do it from now on (specially because you won't be casting your data all the way instead of just using `cast(Something*)(voidPointerData)`:


This is an example of my generic audio buffer pool for various audio APIs
```d
union HipAudioBuffer
{
    version(OpenAL)
    {
        import openal;
        ALuint al;
    }
    version(OpenSLES)
    {
        import opensles.slinterface;
        SLIBuffer* sli;
    }
    version(XAudio2)
    {
        import directx.xaudio2;
        XAUDIO2_BUFFER* xaudio;
    }
}
```

Then, instead of just casting your data from void*, you can just access the "cast" itself as a property.


Reply via email to