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.