【问题标题】:Somehow tell compiler to "Do not process line of code"不知何故告诉编译器“不要处理代码行”
【发布时间】:2018-10-07 21:58:52
【问题描述】:

我正在尝试创建一个用于调试日志记录的宏。这是一个额外的简化版本:

#if defined _DEBUG
#define LOG std::cout
#else
#define LOG IGNORETHISLINEOFCODE
#endif

/* ... */

LOG << "Here's some debug code";

我一直在考虑如何告诉编译器忽略这行以“LOG”开头的代码。我个人不是在寻找替代方法,例如#define LOG( ... ) (void)0。这是我尝试过的:

  • 将 void 的左移运算符重载为不执行任何操作的内联 constexpr(这仍会导致它在反汇编中可见;我不希望这样)

  • 将 LOG 定义为:#define LOG //,但注释标识符未替换

有什么想法吗?就像我之前说的,我不想要任何替代方案,例如用#if defined _DEBUG包围所有日志代码

【问题讨论】:

  • 如果您只关心cout,您就不能将流重定向到空吗? stackoverflow.com/questions/8246317/…
  • @ClausJørgensen 这很有趣!将研究使用/测试它
  • @Tas 不幸的是,目标只是让编译器无法识别代码。这是一个好主意,如果我没有这样的特定限制,它会起作用:(
  • “告诉编译器忽略这行代码......我个人不是在寻找替代方法” 这很可能是不可能的。您可以做的是创建一个无操作重载&lt;&lt; 的类。这些行仍将被处理,但任何启用优化的体面的编译器在大多数情况下都不应该为它们发出任何代码。

标签: c++


【解决方案1】:

如果您的 C++ 版本可以处理 if constexpr,那么对于您的要求,我已经开始喜欢这条路线。

#include <iostream>

template <bool Log>
struct LOGGER {
    template <typename T>
    LOGGER& operator<<(T const &t) {
        if constexpr (Log)
            std::cout << t;
        return *this;
    }
};

LOGGER<false> LOG;

int main (int argc, char const* argv[])
{
    LOG << "A log statement." << '\n';
    return 0;
}

【讨论】:

  • 反汇编显示了对象跟踪,但这非常好,因为它实际上并没有显示任何推送到记录器流的对象。
  • 确实如此。它也不适用于其他操纵器。如果您想要一个完整的实现,那么编写这些方法将需要更多的努力,就像人们可能编写的许多其他流专业化一样。这种努力留给那些希望使用该技术的人作为练习。
【解决方案2】:

您的问题和约束(“我不想要任何替代品”)非常具体。

我一直在思考如何让编译器忽略这行以“LOG”开头的代码

不要这样做,它会被多行日志语句轻易破坏。最好避免任何可能由于其他合法的重新格式化而突然中断的代码。

接下来是

...这仍然导致它在反汇编中可见...

如果代码真的死了,你有一个不错的编译器,并且你打开了优化,这不应该是真的。不过,这仍然是一些工作。

通常的解决方案是这样的

#ifdef NDEBUG
#define LOG(EXPR)
#else
#define LOG(EXPR) std::cerr << EXPR
#endif

这个替代方案,但不是替代方案比如用#if defined包围所有的日志代码,所以不知道是不是有问题不管你是不是。

它确实具有在任何优化级别真正编译为空的优势。

【讨论】:

  • 多行日志记录的好点!我确实喜欢这种通常的解决方案,因为它支持多行日志记录...
【解决方案3】:

基于编译器优化能力的另一种可能性:

#define LOG if (DEBUG) std::cout

现在你可以使用

#define DEBUG false
LOG << "hello " << " world 1" << endl;

您应该也可以使用const bool DEBUG = false

【讨论】:

    【解决方案4】:
    #if defined _DEBUG
    #define LOG std::cout
    #else
    #define LOG /##/
    #endif
    

    这也有效。这是原始问题的答案,所以我会这样标记,但要知道这不支持多行操作。

    我想您可以对多行​​操作执行以下操作。不知道效果如何。

    #if defined _DEBUG
    #define LOG( in ) std::cout << in
    #else
    #define LOG( in ) /##/
    #endif
    

    【讨论】:

      【解决方案5】:

      更好的逻辑是定义跟踪器策略,您可以在应用程序启动时设置日志记录级别,然后使用跟踪级别来决定是否记录调试信息。跟踪级别可以定义为类似的枚举

      enum Tracelevel{CRITICAL, ERROR, INFO, TEST, DEBUG};
      
      setTraceLevel(TraceLevel trcLvl){
          _traceLevel = trcLvl;
      };
      
      #if defined _DEBUG
      if(_traceLevel  == DEBUG) {\
      #define LOG std::cout
      }
      #endif
      

      轻量级记录器可以找到http://www.drdobbs.com/cpp/a-lightweight-logger-for-c/240147505?pgno=1

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-08-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多