C++ 检查整型常量在编译时具有不同的值

C++ 检查整型常量在编译时具有不同的值,c++,compilation,C++,Compilation,我的问题如下。我有大量用作标识符的静态常量整数。出于这个原因,我想知道是否有可能在编译时检查是否有多个常量具有相同的值(某种类型的静态断言…) 我不想使用枚举,因为这些常量是在不同的模块中定义的,我也不想使用一个很长的枚举来处理所有这些常量(其中一些常量彼此不相关) 这里有一个基本示例: // module: foo.h const uint32_t ELEMENT_TYPE_FOO_X = 46; const uint32_t ELEMENT_TYPE_FOO_Y = 51; ... //

我的问题如下。我有大量用作标识符的静态常量整数。出于这个原因,我想知道是否有可能在编译时检查是否有多个常量具有相同的值(某种类型的静态断言…)

我不想使用枚举,因为这些常量是在不同的模块中定义的,我也不想使用一个很长的枚举来处理所有这些常量(其中一些常量彼此不相关)

这里有一个基本示例:

// 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;
错误:元素类型和元素类型的值相同

我根本不是专家,我唯一想到的检测这个错误的方法就是模板专门化

template<uint32_t N>
struct element_traits {
};

template<ELEMENT_TYPE_FOO_X> {
    enum { value = ELEMENT_TYPE_FOO };
};
模板
结构元素特征{
};
模板{
枚举{value=ELEMENT_TYPE_FOO};
};
但这似乎是一个复杂的解决方案。我不知道是否有更优雅/更好的解决方案。到目前为止我还没有找到任何东西


提前感谢。

您当然可以使用宏执行此操作:

#define UNIQUE_CONSTANT(variable, value) \
  const uint32_t variable = value; \
  bool constant_val_##value = value;
如果使用同一个值两次,则会出现多定义错误


(从技术上讲,这将在链接时而不是编译时检测错误。)

基于Keith的解决方案。我可以“检查”常量对于调试构建具有唯一值,而对于发布构建则跳过它

#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

如果大量常量必须是不同的,并且必须在不同的源文件中定义,则可以通过这种方式生成它们,例如,从包含文件名和相应常量名的文件开始,然后在每次生成时生成其余的常量

输入文件:

[foo.h]
ELEMENT_TYPE_FOO_X
ELEMENT_TYPE_FOO_Y

[boo.h]
ELEMENT_TYPE_BOO_C
ELEMENT_TYPE_BOO_D
剧本:

#/usr/bin/env python
从ConfigParser导入SafeConfigParser
从itertools导入计数
config=SafeConfigParser(允许\u否\u值=True)
config.optionxform=lambda x:x#按原样使用名称
config.read('input.cfg')
计数器=计数(1)
对于config.sections()中的文件名:
将open(filename,'w')作为f:
对于(name,ui),zip中的i(config.items(filename),计数器):
f、 写入(“常量uint32\u t%s=%s;\n”%(名称,i))

在代码库中进行一次老式的搜索怎么样?这些常量有什么共同点可以让你处理它们吗?卢奇安·格里戈尔:你说的“在代码库中搜索”是什么意思,它们没有任何共同点。您可以将类型从
uint32\u t
更改为类似
class my\u id\u type
?如果是这样,您可能会找到一种使用模板递归的方法来实现这一点。这是个不错的主意。但是内存消耗有不必要的增加(就像我的解决方案一样)。如果我找不到其他东西,我想我会选择在运行时检查这些值。每个常量一个字节看起来并没有那么大的内存占用。如果你的链接器是好的,那些额外的变量永远不会被引用,可以从最终的可执行文件中删除。如果将第三行替换为
struct unique_id_35;#value{}
则不应存在内存占用。您只是声明了一个未使用的空数据结构。唯一的问题是在不同的名称空间中使用此宏将不起作用:数据不区分大小写。0xFFEF!=0xffef!=65519