【问题标题】:Multi-line macro defining another set of macros定义另一组宏的多行宏
【发布时间】:2017-02-16 21:14:24
【问题描述】:

在我的项目中,我有很多文件,我想使用 C++ 宏来管理调试。对于每个文件,我想使用它自己的开关来启用或禁用调试并调整调试级别。所以基本上有设置的共享文件:

这是共享文件 debug.h 的外观:

#define DEBUG_LEVEL_LOG             -1
#define DEBUG_LEVEL_NONE            0
#define DEBUG_LEVEL_ERROR           1
#define DEBUG_LEVEL_WARNING         2
#define DEBUG_LEVEL_INFO            3
#define DEBUG_LEVEL_DEBUG           4
#define DEBUG_LEVEL_TRACE           5

#ifndef ON
#define ON  1
#endif

#ifndef OFF
#define OFF 0
#endif

// setings for component "wireless"
#define WIRELESS_DEBUGGING                  ON
#define WIRELESS_DEBUGGING_LEVEL            DEBUG_LEVEL_ERROR

// settings for another components
...

在我想使用此设置进行调试的每个文件中,我都需要定义另一组宏。例如文件“wireless.h”

#ifndef WIRELESS_DEBUGGING
#define WIRELESS_DEBUGGING_LEVEL            DEBUG_LEVEL_NONE
#endif

#if WIRELESS_DEBUGGING
    #if WIRELESS_DEBUGGING_LEVEL >= DEBUG_LEVEL_LOG
        #define WIRELESS_LOG(...);          Logger::log(__VA_ARGS__);
    #else
        #define WIRELESS_LOG(...);          {}
    #endif

    #if WIRELESS_DEBUGGING_LEVEL >= DEBUG_LEVEL_ERROR
        #define WIRELESS_ERROR(...);        Logger::error(__VA_ARGS__);
    #else
        #define WIRELESS_ERROR(...);        {}
    #endif

    #if WIRELESS_DEBUGGING_LEVEL >= DEBUG_LEVEL_WARNING
        #define WIRELESS_WARNING(...);      Logger::warning(__VA_ARGS__);
    #else
        #define WIRELESS_WARNING(...);      {}
    #endif

    #if WIRELESS_DEBUGGING_LEVEL >= DEBUG_LEVEL_INFO
        #define WIRELESS_INFO(...);         Logger::info(__VA_ARGS__);
    #else
        #define WIRELESS_INFO(...);         {}
    #endif

    #if WIRELESS_DEBUGGING_LEVEL >= DEBUG_LEVEL_DEBUG
        #define WIRELESS_DEBUG(...);        Logger::debug(__VA_ARGS__);
    #else
        #define WIRELESS_DEBUG(...);        {}
    #endif

    #if WIRELESS_DEBUGGING_LEVEL >= DEBUG_LEVEL_TRACE
        #define WIRELESS_TRACE(...);        Logger::trace(__VA_ARGS__);
    #else
        #define WIRELESS_TRACE(...);        {}
    #endif

#else
    #define WIRELESS_LOG(...);              {}
    #define WIRELESS_ERROR(...);            {}
    #define WIRELESS_WARNING(...);          {}
    #define WIRELESS_INFO(...);             {}
    #define WIRELESS_DEBUG(...);            {}
    #define WIRELESS_TRACE(...);            {}
#endif

当我想调试给定的组件时,我只需使用类似这样的东西(在 wireless.cpp 中)

WIRELESS_TRACE("wireless: hello world\n");
... etc ...

到目前为止,它正在工作。这里是一个问题:我不想在我使用的每个组件中使用类似于文件“wireless.h”中定义的“本地”一堆定义,我只使用不同的前缀。而不是这个,我想要一些看起来类似于这个的“超级宏”

REGISTER_DEBUG(WIRELESS);

有没有办法使用一些连接和多行宏来实现这一点?我发现在#define 中使用#define 是被禁止的。

【问题讨论】:

  • 更好地使用强类型的东西(这是 C++ 主要提供的优于 C 的东西),以及使用 RAII 的自动化清理。对于调试,请使用一个不错的 GUI 调试器,例如 Visual Studio 中的调试器。简而言之,在这还不够的情况下,好的预防性编程和好的工具。
  • 您希望在编译时控制多少消息,以及您希望在运行时控制多少。例如,您是否希望能够传递参数“--debug-level=trace”并期望打印所有“trace”消息?

标签: c++ macros


【解决方案1】:

我不完全确定你想要什么,所以如果这不合适,请告诉我,我会删除。

有可能在预处理器中使用## 连接标记。例如,请参阅https://gcc.gnu.org/onlinedocs/cpp/Concatenation.html

【讨论】:

    【解决方案2】:

    这有点笨拙,但应该可以解决问题:

    #define DEBUG_LEVEL_LOG             -1
    #define DEBUG_LEVEL_NONE            0
    #define DEBUG_LEVEL_ERROR           1
    #define DEBUG_LEVEL_WARNING         2
    #define DEBUG_LEVEL_INFO            3
    #define DEBUG_LEVEL_DEBUG           4
    #define DEBUG_LEVEL_TRACE           5
    
    #define TRACE(a,...) _TRACE(a,__VA_ARGS__)
    #define _TRACE(a,...) __TRACE_##a(__VA_ARGS__)
    
    #define __TRACE_5(...) do{Logger::trace(__VA_ARGS__);}while(0)
    

    这里是笨拙的:您还需要将__TRACE_4__TRACE_3 等定义为空。然后你需要为 Debug 定义同样的东西:

    #define __DEBUG_4(...) do{Logger::debug(__VA_ARGS__);}while(0)
    

    但最后,在您定义了无线日志级别之后:

    #define WIRELESS_LEVEL 5
    

    你可以像这样调用宏:

    TRACE(WIRELESS_LEVEL,"wireless: hello world\n");
    

    编辑 或者(这可能更干净):

    #define __PRINT_55(...) do{Logger::trace(__VA_ARGS__);}while(0)
    #define __PRINT_44(...) do{Logger::debug(__VA_ARGS__);}while(0)
    
    // etc...
    // Also need to define what you need to be not printed:
    
    #define __PRINT_01(...)
    
    // etc...
    
    #define PRINT(a,b,...) _PRINT(a,b,__VA_ARGS__)
    #define _PRINT(a,b,...) __PRINT_##a##b(__VA_ARGS__)
    

    现在你可以像这样调用你的函数了:

    PRINT(DEBUG_LEVEL_TRACE, WIRELESS_LEVEL, "Hello world\n");
    

    【讨论】:

      【解决方案3】:

      您可以通过从宏切换到内联函数来实现。像这样的:

      // debug.h
      enum DebugLevel {
          DEBUG_LEVEL_LOG = -1,
          DEBUG_LEVEL_NONE = 0,
          DEBUG_LEVEL_ERROR = 1,
          DEBUG_LEVEL_WARNING = 2,
          DEBUG_LEVEL_INFO = 3,
          DEBUG_LEVEL_DEBUG = 4,
          DEBUG_LEVEL_TRACE = 5
      };
      
      // settings for component "wireless"
      constexpr bool WIRELESS_DEBUGGING = true;
      constexpr DebugLevel WIRELESS_DEBUGGING_LEVEL = DEBUG_LEVEL_ERROR;
      
      #define REGISTER_DEBUG_FUNC(topic, level, func) \
      template <typename... Args> \
      inline void topic##_##level(Args&& ... args) { \
          if ( topic##_DEBUGGING && topic##_DEBUGGING_LEVEL >= DEBUG_LEVEL_##level ) \
              Logger::func(std::forward<Args>(args)...); \
      }
      
      #define REGISTER_DEBUG(topic) \
          REGISTER_DEBUG_FUNC(topic, LOG, log) \
          REGISTER_DEBUG_FUNC(topic, ERROR, error) \
          REGISTER_DEBUG_FUNC(topic, WARNING, warning) \
          REGISTER_DEBUG_FUNC(topic, INFO, info) \
          REGISTER_DEBUG_FUNC(topic, DEBUG, debug) \
          REGISTER_DEBUG_FUNC(topic, TRACE, trace)
      
      // wireless.h
      REGISTER_DEBUG(WIRELESS)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-17
        • 2015-10-20
        相关资源
        最近更新 更多