【问题标题】:How to comment lines automatically in release mode?如何在发布模式下自动注释行?
【发布时间】:2010-12-12 15:09:17
【问题描述】:

我只需要在调试模式下让一些代码行“活动”,而在发布模式下被忽略。 有没有办法做这样的事情:

#include <iostream>
using namespace std;

#ifdef _TEST_
#define _cerr cerr
#else
#define _cerr // cerr
#endif

int main() {
   _cerr << "TEST message" << endl;
}

这样当_TEST_ 未定义时,一些行会被注释掉,或者从代码中删除。我知道 cmets 在其余部分之前被处理,所以这段代码是错误的。但是,如果不明确使用#ifdefs,我怎样才能获得我需要的行为呢?

【问题讨论】:

    标签: c++ debugging c-preprocessor release release-mode


    【解决方案1】:

    创建您自己的 NULL 流。

    #include <iostream>
    
    class NullStream    {};
    template<typename T>
    NullStream& operator <<(NullStream& n,T const& data)                        {return n;}
    NullStream& operator <<(NullStream& n,std::ostream& (*)(std::ostream&))     {return n;}
    
    #ifdef  _TEST_
    #define myerr       std::cerr
    #else
    NullStream  myerrstream;
    #define myerr       myerrstream
    #endif
    
    int main()
    {
        myerr << "Hi" << std::endl;;
        myerr << std::endl;;
    }
    

    【讨论】:

      【解决方案2】:

      “无登录版本”的更好解决方案是以下类:

      class NullStream {
         template<typename T> NullStream& operator<< const(T&) { }
      };
      

      用途:

      #ifdef DEBUG
      #define CERR std::cerr
      #else
      #define CERR NullStream()
      #endif
      

      【讨论】:

      • 不是更好:参数将被评估......即使这是无用的!
      • 没错,但是当你写信给例如时你也会遇到这个问题。一个字符串流。这节省了operator&lt;&lt;(ostream&amp;, T)ostreambuf 的开销
      【解决方案3】:

      如果您追求的是在发布版本中删除的调试日志记录,您可以执行以下操作:

      #ifdef _TEST_
      #define LOG(x) (cerr << x << endl)
      #else
      #define LOG(x)
      #endif
      
      ...
      
      int main() {
          LOG("TEST message");
      }
      

      【讨论】:

        【解决方案4】:

        将 _cerr 定义为空将导致编译失败。您可以改为定义一个在发布模式下排除的宏。

        例如:

        #ifdef _TEST_
        #define LOG_ERROR(log) cerr << log << endl;
        #else
        #define LOG_ERROR(log) 
        #endif
        

        然后在你的代码中:

        int main() {
           LOG_ERROR("TEST message");
        }
        

        【讨论】:

        • 他并没有试图将其定义为空。他希望注释斜线将包含在宏扩展中,因此结果将是注释掉的日志行。
        【解决方案5】:

        这基本上可以满足您的要求:

        #ifdef _TEST_
        #define _cerr  cerr
        #else
        #define _cerr  if (1) {} else cerr
        #endif
        

        但是,如果您编写类似这样的内容,例如收到关于模棱两可 else 的编译器警告,请不要感到惊讶:

        if (something)
          _cerr << "Why?" << std::endl;
        

        您应该始终意识到这个_cerr 实际上是一个重要的宏。

        【讨论】:

          【解决方案6】:

          没有。绝对没有。

          试试这个的变体:

          #ifdef _TEST_
              ostream& _cerr = cerr;
          #else
              ostringstream _cerr;
          #endif
          

          (基本上你会想要一个丢弃其输入的流。)

          【讨论】:

          • 首先,我相信使用带有下划线前缀的全局名称是为实现保留的。其次,丢弃其输入的流不会阻止对参数进行评估,这使得这种方法在任何对性能敏感的上下文中都无用。
          【解决方案7】:

          使用这个:

          #ifdef _TEST_
          #define DEBUG_TEST(x) x
          #else
          #define DEBUG_TEST(x)
          #endif
          
          int main() {
              DEBUG_TEST(_cerr << "TEST message" << endl);
          }
          

          【讨论】:

            【解决方案8】:
            int main() {
            #ifdef _TEST_
               _cerr << "TEST message" << endl;
            #endif
            }
            

            【讨论】:

              【解决方案9】:

              您可以为此使用宏:

              #ifdef _TEST_
              #define DEBUG_ONLY(x) x;
              #else
              #define DEBUG_ONLY(x)
              #endif
              
              int main() {
                  DEBUG_ONLY(cerr << "TEST message" << endl)
              }
              

              【讨论】:

              • 不在宏中添加分号会使您的代码更像 C++(强制用户在 DEBUG_ONLY 子句之后添加 ;
              • 我看到这个宏的唯一问题是你只能使用一个语句。我个人更喜欢 do { x; } while(0) 子句来允许宏中的多个语句(即使一些编译器抱怨 while(0) 部分......:/)
              【解决方案10】:

              ifdefs 是要走的路。你怎么知道编译器是否处于发布与调试模式?除了在预处理阶段之外,还会在什么时候进行沟通?您可以在其他什么阶段决定删除/添加代码(除了在模板生成期间)。嘿,也许我们可以使用模板生成...但是您仍然必须以某种方式关闭 ifdef 以控制您的模板。

              也许有一种我没有想到的非常巧妙的方法来做到这一点,但每个人都知道/使用 ifdefs 来达到这个目的。如果你扔给他们一个曲线球,它只会大大增加维护代码的人力成本。

              坚持使用 ifdefs。

              【讨论】:

                猜你喜欢
                • 2013-04-26
                • 1970-01-01
                • 2014-07-13
                • 1970-01-01
                • 1970-01-01
                • 2011-11-29
                • 2013-05-30
                • 1970-01-01
                • 2012-06-30
                相关资源
                最近更新 更多