如何比较两个同名的预处理器宏?
How to compare two preprocessor macros with the same name?
我有一个项目,其中有两个具有相同名称的不同预处理器宏,定义在两个不同的包含文件(来自两个不同的库)中,我必须在构建时检查它们是否具有相同的值。
到目前为止,我可以在 运行 时进行此检查,将宏值分配给不同实现文件中的不同变量,每个变量仅包括所涉及的 headers 之一。
如何在构建时完成?
这是我到目前为止尝试过的(其中 Macro1.h 和 Macro2.h 是我无法修改的 third-party 文件):
Header 个文件:
TestMultiMacros.h:
#ifndef TEST_MULTI_MACROS_H
#define TEST_MULTI_MACROS_H
struct Values
{
static const unsigned int val1, val2;
static const unsigned int c1 = 123, c2 = 123;
};
#endif // TEST_MULTI_MACROS_H
Macro1.h:
#ifndef MACRO1_H
#define MACRO1_H
#define MY_MACRO 123
#endif // MACRO1_H
Macro2.h:
#ifndef MACRO2_H
#define MACRO2_H
#define MY_MACRO 123
#endif // MACRO2_H
实现文件:
TestMultiMacros1.cpp:
#include "TestMultiMacros.h"
#include "Macro1.h"
const unsigned int Values::val1 = MY_MACRO;
TestMultiMacros2.cpp:
#include "TestMultiMacros.h"
#include "Macro2.h"
const unsigned int Values::val2 = MY_MACRO;
entrypoint.cpp:
#include "TestMultiMacros.h"
using namespace std;
static_assert(Values::val1 == Values::val2, "OK"); // error: expression did not evaluate to a constant
static_assert(Values::c1 == Values::c2, "OK");
int main()
{
}
我对同时使用 C++11 和 C++17 的解决方案感兴趣。
包括第一个 header。然后将宏的值保存到一个constexpr
变量中:
constexpr auto foo = MY_MACRO;
然后包括第二个 header。它应该默默地覆盖 MY_MACRO
。如果您的编译器开始报错,请先执行 #undef MY_MACRO
。
然后使用 static_assert
:
将宏的新值与变量进行比较
static_assert(foo == MY_MACRO, "whatever");
这是一个非常简单的 C++17 测试,它通过比较宏展开的文本来处理任意(非函数)宏。对于c++11,缺少std::string_view
中的constexpr
比较,可以自己写几行,如this answer.
#include <string_view>
#define STRINGIFY(x) STRINGIFY_(x)
#define STRINGIFY_(x) #x
#include "macro1.h"
//#define MY_MACRO A night to remember
constexpr const char* a = STRINGIFY(MY_MACRO);
#undef MY_MACRO
#include "macro2.h"
//#define MY_MACRO A knight to remember
constexpr const char* b = STRINGIFY(MY_MACRO);
static_assert(std::string_view(a) == b, "Macros differ");
int main() { }
(神箭: https://godbolt.org/z/nH5qVo)
当然,这取决于你所说的宏相等的确切含义。如果一个头文件有
,这个版本会报错
#define MY_MACRO (2+2)
另一个有
#define MY_MACRO 4
同样值得注意的是,字符串化规范化了空白,但除了修剪结尾之外,它并没有规范化空白的存在。所以 (2 + 2)
和 (2 + 2)
将比较相等,但 (2+2)
和 ( 2 + 2 )
不会
我有一个项目,其中有两个具有相同名称的不同预处理器宏,定义在两个不同的包含文件(来自两个不同的库)中,我必须在构建时检查它们是否具有相同的值。
到目前为止,我可以在 运行 时进行此检查,将宏值分配给不同实现文件中的不同变量,每个变量仅包括所涉及的 headers 之一。
如何在构建时完成?
这是我到目前为止尝试过的(其中 Macro1.h 和 Macro2.h 是我无法修改的 third-party 文件):
Header 个文件:
TestMultiMacros.h:
#ifndef TEST_MULTI_MACROS_H
#define TEST_MULTI_MACROS_H
struct Values
{
static const unsigned int val1, val2;
static const unsigned int c1 = 123, c2 = 123;
};
#endif // TEST_MULTI_MACROS_H
Macro1.h:
#ifndef MACRO1_H
#define MACRO1_H
#define MY_MACRO 123
#endif // MACRO1_H
Macro2.h:
#ifndef MACRO2_H
#define MACRO2_H
#define MY_MACRO 123
#endif // MACRO2_H
实现文件:
TestMultiMacros1.cpp:
#include "TestMultiMacros.h"
#include "Macro1.h"
const unsigned int Values::val1 = MY_MACRO;
TestMultiMacros2.cpp:
#include "TestMultiMacros.h"
#include "Macro2.h"
const unsigned int Values::val2 = MY_MACRO;
entrypoint.cpp:
#include "TestMultiMacros.h"
using namespace std;
static_assert(Values::val1 == Values::val2, "OK"); // error: expression did not evaluate to a constant
static_assert(Values::c1 == Values::c2, "OK");
int main()
{
}
我对同时使用 C++11 和 C++17 的解决方案感兴趣。
包括第一个 header。然后将宏的值保存到一个constexpr
变量中:
constexpr auto foo = MY_MACRO;
然后包括第二个 header。它应该默默地覆盖 MY_MACRO
。如果您的编译器开始报错,请先执行 #undef MY_MACRO
。
然后使用 static_assert
:
static_assert(foo == MY_MACRO, "whatever");
这是一个非常简单的 C++17 测试,它通过比较宏展开的文本来处理任意(非函数)宏。对于c++11,缺少std::string_view
中的constexpr
比较,可以自己写几行,如this answer.
#include <string_view>
#define STRINGIFY(x) STRINGIFY_(x)
#define STRINGIFY_(x) #x
#include "macro1.h"
//#define MY_MACRO A night to remember
constexpr const char* a = STRINGIFY(MY_MACRO);
#undef MY_MACRO
#include "macro2.h"
//#define MY_MACRO A knight to remember
constexpr const char* b = STRINGIFY(MY_MACRO);
static_assert(std::string_view(a) == b, "Macros differ");
int main() { }
(神箭: https://godbolt.org/z/nH5qVo)
当然,这取决于你所说的宏相等的确切含义。如果一个头文件有
,这个版本会报错#define MY_MACRO (2+2)
另一个有
#define MY_MACRO 4
同样值得注意的是,字符串化规范化了空白,但除了修剪结尾之外,它并没有规范化空白的存在。所以 (2 + 2)
和 (2 + 2)
将比较相等,但 (2+2)
和 ( 2 + 2 )