0

I have a type, morton_id_t, which is a 64-bit number. I have a second type which is a concatenation of the bits of a Morton ID (morton_id_t) with several bits that contain information about the level in a tree:

typedef uint64_t morton_id_t;
typedef uint64_t morton_id_lvl_t;

#define BITS (sizeof(morton_id_lvl_t) * 8)

// number of bits to store the level
#define LEVEL_BITS 6
#define LEVEL_MASK ((1 << LEVEL_BITS) - 1)

// utility functions to pull the level or morton id out of a morton_id_lvl_t
lvl_t level(morton_id_lvl_t n);
morton_id_t morton_id(morton_id_lvl_t n);

// this just strips off the level bits using the `morton_id` function...
bool isAncestor(morton_id_lvl_t ancestor, morton_id_lvl_t descendent);

// ...and calls this
bool isAncestor(morton_id_t ancestor, morton_id_t descendent);

morton_id_t is just typedef'ed from uint64_t even though I only need the 64 - 6 level bits.

The compiler throws an error saying that the second isAncestor definition redefines the first, even though the type signatures are different.

How can I define two different isAncestor functions, one of which takes morton_id_lvl_t's and the other takes morton_id_t's?

Do I need to use classes instead of typedef's?

aaronstacy
  • 6,189
  • 13
  • 59
  • 72

2 Answers2

5

morton_id_t and morton_id_lvl_t are the same, so the isAncestor signatures are the same too.

A typedef does not create a new type, but rather an alias for an existing one.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
1

A typedef only introduces a new name for a type, it doesn't create a new type, unfortunately.

You could wrap them in structs to turn them into different types:

struct morton_id_t
{
    uint64_t id;
};

struct morton_id_lvl_t
{
    uint64_t id_lvl;
};

or possibly (not 100% sure that it's valid):

struct morton_id_lvl_t
{
    uint64_t id:58;
    uint64_t level:6;
};

This would also provide type safety for your conversion functions.

molbdnilo
  • 64,751
  • 3
  • 43
  • 82