user1192525
user1192525

Reputation: 677

check integer constants have different values at compilation time

My question is the following. I have a large number of static const integers that work as Identifiers. For this reason I would like to know if it is possible to check at compilation time if there is more than one constant with the same value (some kind of static assert...).

I do not want to use an enum as these constants are defined in different modules and I don't want to have like a very long enum with all of them (and some of them are not related to each other).

Here you have a basic example:

// module: foo.h
const uint32_t ELEMENT_TYPE_FOO_X = 46;
const uint32_t ELEMENT_TYPE_FOO_Y = 51;
...

// module: boo.h
const uint32_t ELEMENT_TYPE_BOO_C = 21;
const uint32_t ELEMENT_TYPE_BOO_D = 51;

error: ELEMENT_TYPE_FOO_Y and ELEMENT_TYPE_BOO_D have the same value.

I'm not an expert at all and the only thing that comes to my mind to detect this error is template specialization.

template<uint32_t N>
struct element_traits {
};

template<ELEMENT_TYPE_FOO_X> {
    enum { value = ELEMENT_TYPE_FOO };
};

But it seems to be a complex solution. I don't know if there is a more elegant/better solution. I haven't found anything so far.

Thanks in advance.

Upvotes: 3

Views: 317

Answers (3)

jfs
jfs

Reputation: 414179

If large number of constants must be different and must be defined in different source files then you could generate them that way e.g., start with a file that contains filenames and corresponding constant names and generate the rest at each build.

Input file:

[foo.h]
ELEMENT_TYPE_FOO_X
ELEMENT_TYPE_FOO_Y

[boo.h]
ELEMENT_TYPE_BOO_C
ELEMENT_TYPE_BOO_D

The script:

#!/usr/bin/env python
from ConfigParser import SafeConfigParser
from itertools import count

config = SafeConfigParser(allow_no_value=True)
config.optionxform = lambda x: x # use names as-is
config.read('input.cfg')

counter = count(1)
for filename in config.sections():
    with open(filename, 'w') as f:
         for (name, _), i in zip(config.items(filename), counter):
             f.write("const uint32_t %s = %s;\n" % (name, i))

Upvotes: 0

user1192525
user1192525

Reputation: 677

Based on Keith's solution. I could "check" constants have unique value for debug build and skip it for release build.

#ifdef DEBUG
#define DEFINE_UNIQUE_CONSTANT(variable, value) \
    const uint32_t variable = value;            \
    uint32_t constant_val_##value = value;
#else
#define DEFINE_UNIQUE_CONSTANT(variable, value) \
    const uint32_t variable = value;
#endif

Upvotes: 0

Keith Randall
Keith Randall

Reputation: 23265

You could certainly do this using macros:

#define UNIQUE_CONSTANT(variable, value) \
  const uint32_t variable = value; \
  bool constant_val_##value = value;

Then you will get a multiple definition error if the same value is used twice.

(Technically, this will detect the error at link time, not compile time.)

Upvotes: 6

Related Questions