Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/150.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 必须有一个;定义为;宏检查及其调用是否处于单独的状态?_C++_C Preprocessor - Fatal编程技术网

C++ 必须有一个;定义为;宏检查及其调用是否处于单独的状态?

C++ 必须有一个;定义为;宏检查及其调用是否处于单独的状态?,c++,c-preprocessor,C++,C Preprocessor,我一直在努力从很多关于这个主题的文章中找到答案,但是这里有一些看似无辜的代码,当F不是一个定义的宏时无法编译 int main() { #if defined(F) && F(0, 2, 0) return 0; #endif return 1; } 根据,问题在于#如果表达式中的“表达式中的所有宏都在表达式值的实际计算开始之前展开”,那么这是一个无效的检查,因为F未定义时 test.cpp:2:20: error: missing binary operator be

我一直在努力从很多关于这个主题的文章中找到答案,但是这里有一些看似无辜的代码,当
F
不是一个定义的宏时无法编译

int main() {
#if defined(F) && F(0, 2, 0)
  return 0;
#endif
  return 1;
}
根据,问题在于
#如果
表达式中的“表达式中的所有宏都在表达式值的实际计算开始之前展开”,那么这是一个无效的检查,因为
F
未定义时

test.cpp:2:20: error: missing binary operator before token "("
 #if defined(F) && F(0, 2, 0)
                    ^
我的问题是:这样做的唯一正确方法是什么

int main() {
#if defined(F)
#if F(0, 2, 0)
  return 0;
#endif
#endif
  return 1;
}

我觉得这非常难看和不直观,所以我希望在预处理器中有一种更好的方法来做这些事情。

假设在某个头文件中定义了
F
宏,您可以将以下代码放在include和它的第一次使用之间的某个地方:

#ifndef F
#define F(a,b,c) 0
#endif
或者另一个合理的违约。这是解决你问题的常用方法。另一种方法是不允许使用此类宏 未定义,但需要默认值或任何预期值。后一种方法是 对于配置文件来说,有点安全,因为作者明确地考虑了宏和故意。 选择了一个值(即他没有忘记定义它)。如果定义在同一个文件中,也会更容易

您的测试将是:

#if F(0, 2, 0)
避免嵌套条件(如果某个地方需要
#else
,则会导致额外的问题)

两句忠告:

  • 谨慎使用,只在合理的情况下使用宏。特别是C++提供了减少宏需求的特性。
  • 不要对宏使用单字母名称。记住它们是文本替换,这是正常的语言语法。请改用自解释名称(这不仅适用于宏,而且对于那些更相关的宏)

对你来说可能是丑陋的,直觉的,但是如果它是C++的(绝对的)和C的(通常不是),如果无论如何,不鼓励使用类似于宏的函数,因此找到一个解决问题的方法来避免或尽量减少使用宏是值得的。如上所述,不清楚为什么需要这样做,所以没有人能帮到你。对于MSVC10,第一个方法对我有效,但对约束条件稍作更改,我会定义一个默认值
那么在什么情况下不定义
F
呢?您实际要解决的问题是什么?一个有两个返回的函数?在返回1;之前可以使用#else。谢谢,在真实的示例中,F是第三方库检查版本,这是作为库更新的一部分引入的一个新宏。我的收获是给我们的将嵌套条件(丑陋的版本)添加到其他用户试图根据旧版本的lib进行编译的情况下进行验证。感谢您的回答。标识符可能不会以数字开头。尽管如此,我还是希望您能这样做(在示例中我可以使用一个简短的名称),但问题和答案对未来的读者很有帮助,因此我不得不添加警告。与其他一些用户相比,我使用最合适的结构,如果这意味着宏,我对它们没意见。同意,我又编了一个名称,它是一个愚蠢的库名称,在上面没有任何意义,希望它对未来的读者仍然有用,如果他们点击这个:)检查我最近的答案。如果我认为这不值得,我就不会回答。正如我所写的:不需要使用实际名称(但——说真的:宏名称不能以数字开头。这是语言所不允许的;它将被解释为一个数字,后面有无效字符。嗯…