问题 有没有办法让C预处理器解析#error语句中的宏?


正如标题所说。我想在#error语句的文本中使用预处理器宏:

#define SOME_MACRO 1

#if SOME_MACRO != 0
    #error "SOME_MACRO was not 0; it was [value of SOME_MACRO]"
#endif

在这个例子中,我想要预处理器来解决 [value of SOME_MACRO] 到实际价值 SOME_MACRO 在这种情况下是1.这应该在预处理器,编译器或任何进程#error打印错误输出之前发生
有没有办法做到这一点,或者这是不可能的?

我不想知道是否有ISO C ++标准方法来做到这一点,因为afaik预处理器指令 #error 在任何ISO C ++标准中都没有说明。但是,我知道GCC和Visual C ++的支持 #error。但我的问题不是那些编译器特有的,我只是好奇,如果任何C / C ++编译器/预处理器都能做到这一点。

我试图搜索那个话题,但没有任何运气。


12380
2018-05-14 14:55


起源

如果你正在使用C ++ 0x static_assert几乎可以做到这一点,或者你可以使用boost中支持更多编译器的那个。我不知道有任何其他方法可以实现此功能。 - Flexo♦
#error实际上是标准C ++的一部分,但我不知道如何做你想做的事情。 - Neil Butterworth
我还不知道static_assert。它很有用,但我仍然很难将宏的值放入错误文本中。 - Madio


答案:


为了完整性我建议的C ++ 0x方式(使用与Kirill相同的技巧):

#define STRING2(x) #x
#define STRING(x) STRING2(x)

#define EXPECT(v,a) static_assert((v)==(a), "Expecting " #v "==" STRING(a) " [" #v ": "  STRING(v) "]")


#define VALUE 1

EXPECT(VALUE, 0);

得到:

g++ -Wall -Wextra -std=c++0x test.cc                     
test.cc:9: error: static assertion failed: "Expecting VALUE==0 [VALUE: 1]"

5
2018-05-14 17:59



比较喜欢 (v)==(a) - Seth Johnson
@Seth - 好点,编辑。 - Flexo♦
非常好,完美无瑕。现在我必须决定使用哪种方法......技术上,两个答案都是awoodlands和Kirills解决了这个问题。现在我更喜欢static_assert而不是#pragma message / #error one。谢谢你的回答 - Madio


在Visual Studio中,您可以使用 pragmamessage 如下:

#define STRING2(x) #x
#define STRING(x) STRING2(x)

#define SOME_MACRO 1

#if SOME_MACRO != 0
    #pragma message ( "SOME_MACRO was not 0; it was " STRING(SOME_MACRO) )
    #error SOME_MACRO was not 0;
#endif

这将生成两条消息,但您将获得值 SOME_MACRO。在G ++中使用以下代码(来自评论:g ++版本4.3.4适用于括号,如上面的代码):

#pragma message "SOME_MACRO was not 0; it was " STRING(SOME_MACRO)

5
2018-05-14 15:07



有趣,有用。谢谢!如果你有 #pragma 在那里,你需要 #error 当然,如果编译器无法识别编译指示,它将忽略它 - 它只会略微降低诊断性,但在这种情况下你已经做到了最好。此外,括号版本在G ++中工作,因此您可以在MSVC和G ++中使用相同的机制。有趣的是,GCC 4.6.0(与G ++相对)似乎忽略了 #pragma message。 - Jonathan Leffler
谢谢,这就是诀窍:括号版本也适用于G ++版本4.3.4 - Madio


#define INVALID_MACRO_VALUE2(x) <invalid_macro_value_##x>
#define INVALID_MACRO_VALUE(x) INVALID_MACRO_VALUE2(x)

#if SOME_MACRO != 0
  #include INVALID_MACRO_VALUE(SOME_MACRO)
#endif

在Visual Studio 2005中生成“无法打开包含文件:'invalid_macro_value_1':没有此类文件或目录”,并且可能在其他编译器上生成类似的消息。

这并没有直接回答你关于使用#error的问题,但结果是类似的。


3
2018-05-14 22:19



这对我来说也适用于XCode 5.其他任何事情都没有。 - Aidan McKenna