【问题标题】:Is it possible to set pre-processor conditions within a macro?是否可以在宏中设置预处理器条件?
【发布时间】:2011-07-05 07:17:31
【问题描述】:

我正处于这种设计将大大提高我的代码的清晰度和维护需求的位置。

我正在寻找的是这样的:

#define MY_MACRO(arg) #if (arg)>0 cout<<((arg)*5.0)<<endl; #else cout<<((arg)/5.0)<<endl; #endif

这里的想法:
预处理器根据宏参数的编译时(常量)值替换不同的代码行。当然,我知道这种语法不起作用,因为# 被视为字符串化运算符而不是标准的#if,但我认为这展示了预处理器的功能我正在努力实现。

我知道我可以在其中放一个标准的if 语句,然后编译器/运行时将检查该值。但这对于应用程序来说是不必要的工作,因为 arg 将始终传递一个常量值,例如 10.8-12.5,只需要在编译时进行评估。

此数字运算应用程序的性能需求要求尽可能消除所有不必要的运行时条件,并且已使用许多常量值和宏(代替变量和函数)来实现这一点。无需将预处理器代码与真正的if 条件混合即可继续这一趋势的能力将使这变得更加清晰 - 当然,代码清洁度是使用宏时最大的问题之一,尤其是在这个级别。

【问题讨论】:

    标签: c++ conditional c-preprocessor substitution


    【解决方案1】:

    简单,使用真正的 C++:

    template <bool B> void foo_impl       (int arg) { cout << arg*5.0 << endl; }
    template < >      void foo_impl<false>(int arg) { cout << arg/5.0 << endl; }
    template <int I>  void foo            ( )       { foo_impl< (I>0) >(I); }  
    

    [编辑] 或者在现代 C++ 中,if constexpr

    【讨论】:

    • 虽然我承认浮点数更难,因为你不能将它们作为模板参数传递。你仍然可以使用foo_impl&lt; (F&gt;0) &gt;(F); 部分,即使是宏。
    • 我喜欢真正的代码(OOP 或其他,如您的示例)而不是宏。不幸的事实:我在问题中给出的例子是verrry简化的。我的实际代码比这大得多,并且不可能以模板形式进行调试。在这种特殊情况下,宏更好的原因是任何其他解决方案都需要我编写相同的代码文件数十次。将模板添加到组合中,您就有了一些保证不可维护的代码。宏允许我编写一次代码,并根据需要多次复制它。
    • 我不买。模板是不可能调试的,但宏是?调试器在理解模板函数方面要好得多。他们只是有一个时髦的名字,仅此而已。更易维护?模板更好地尊重范围。一次编写,经常使用?当然,模板也可以做到这一点。但是是的,你必须重新学习一些方法。
    【解决方案2】:

    据我所知,您的宏中不能有#if(或类似的东西)。 但是,如果条件在编译时已知,您可以安全地使用普通的if 语句。编译器会对其进行优化(假设您开启了优化)。

    它叫做“Dead code elimination

    【讨论】:

    • 更好的是,我将使用 ?: 运算符来完全“内联”条件。总而言之,我同意这可能是最好的也是唯一的选择。
    • 小心点,使用 ?: 太多会让你的代码难以理解!
    • 点了。无论您使用 ?: 还是 if,死代码通常都以相同的方式显示,因此应考虑清楚。
    • 死代码仍然必须编译。这对于像if (i&gt;0) { int foo[i]; } else { int foo[1-i]; } 这样的代码来说可能会很痛苦。模板是另一种选择。
    猜你喜欢
    • 1970-01-01
    • 2011-04-16
    • 2010-09-23
    • 2015-04-05
    • 2020-09-18
    • 2020-11-21
    • 1970-01-01
    • 2012-09-04
    • 1970-01-01
    相关资源
    最近更新 更多