DEV Community

Discussion on: What I would like to see in containers for C

Collapse
 
curtisfenner profile image
Curtis Fenner • Edited

If they need a mapping for their own types then unfortunately for them they will have to create a map for their specific needs.

... copying and pasting are used and slight changes to the code are made to fit with what is needed.

This isn't needed - C has macros! While large macros aren't usually a great idea, because a concept like a map is extremely well-defined and unlikely to need continuous development, the boost of having less indirection and type-safety is probably worth it.

Here's how it can end up looking

// maps.h
#include "stdlib.h"

#define DEFINE_MAP_IMPLEMENTATION(keyType, valueType, MapType)                 \
  struct MapType##_struct {                                                    \
    size_t count;                                                              \
    keyType* keys;                                                             \
    valueType* values;                                                         \
  };                                                                           \
  MapType* MapType##_create() {                                                \
    MapType* map = (MapType*)malloc(sizeof(MapType));                          \
    map->count = 0;                                                            \
    map->keys = NULL;                                                          \
    map->values = NULL;                                                        \
    return map;                                                                \
  }                                                                            \
  void MapType##_destroy(MapType* map) {                                       \
    free(map->keys);                                                           \
    free(map->values);                                                         \
    free(map);                                                                 \
  }

#define DEFINE_MAP_INTERFACE(keyType, valueType, MapType)                      \
  typedef struct MapType##_struct MapType;                                     \
  MapType* MapType##_create();                                                 \
  void MapType##_destroy(MapType*);

Here's a use of the above to make a InvertedIndex type:

// inverted_index.h
#include "maps.h"

typedef struct {
  size_t documentID;
  size_t offset;
} IndexUse;

DEFINE_MAP_INTERFACE(char const*, IndexUse, InvertedIndex)

and its implementation file:

// inverted_index.c
#include "inverted_index.h"

DEFINE_MAP_IMPLEMENTATION(char const*, IndexUse, InvertedIndex)
Collapse
 
noah11012 profile image
Noah11012

Using macros instead of void pointers for generic containers is a better idea, however, I find a huge macro for the implementation to be cumbersome.