【问题标题】:Using C++ Macros To Check For Variable Existence使用 C++ 宏检查变量是否存在
【发布时间】:2011-03-12 13:00:10
【问题描述】:

我正在为我的库创建一个日志记录工具,并制作了一些不错的宏,例如:

#define DEBUG  myDebuggingClass(__FILE__, __FUNCTION__, __LINE__)
#define WARING myWarningClass(__FILE__, __FUNCTION__, __LINE__)

其中 myDebuggingClass 和 myWarningClass 都有一个重载的

现在,我有一些用户将重载的基类,称为“Widget”,我想将这些定义更改为更像:

#define DEBUG  myDebuggingClass(__FILE__, __FUNCTION__, __LINE__, this)
#define WARNING myWarningClass(__FILE__, __FUNCTION__, __LINE__, this)

这样当用户调用 'DEBUG

最简单的解决方案是定义单独的 WIDGET_DEBUG、WIDGET_WARNING、PLAIN_DEBUG 和 PLAIN_WARNING 宏并将差异记录给用户,但如果有办法解决这个问题,那就太好了。有没有人看到做这种事情的任何技巧?

【问题讨论】:

    标签: c++ macros metaprogramming


    【解决方案1】:

    在Widget类中声明一个全局的Widget* const widget_this = NULL;和一个受保护的成员变量widget_this,初始化为this,然后做

    #define DEBUG myDebuggingClass(__FILE__, __FUNCTION__, __LINE__, widget_this)

    【讨论】:

    • 我应该注意到这个答案在很多方面都是邪恶的。它使用了我不喜欢的宏、我觉得令人反感的变量阴影以及我通常避免使用的受保护的数据成员(尽管我在这里不反对)。此解决方案是对您提出的问题的最快、最直接的答案,但这并不意味着它就是您的问题的答案。
    • 我比这个更喜欢@MSalters 的解决方案。
    【解决方案2】:

    宏基本上是由预处理器完成的直接文本替换。宏无法知道调用它的上下文以进行您感兴趣的检测。

    最好的解决方案可能是您怀疑的单独的宏。

    【讨论】:

      【解决方案3】:

      我认为你不能用宏来做到这一点。您可以可能设法使用 SFINAE 来做到这一点,但是使用 SFINAE(至少直接使用)的代码1很难编写、更难调试,而且对于任何人来说几乎是不可能的,除了专家阅读或理解。如果您真的想这样做,我会尝试看看您是否可以让 Boost enable_if(或其亲属)来处理至少部分肮脏的工作。

      1 ...至少在我所见过的每一种情况下,我都很难想象它不是这样的。

      【讨论】:

      • 除了使用 enable_if 您正在编写依赖于 SFINAE 的代码之外,这与您的论点相反,因为使用 enable_if 相当容易。 enable_if 也没有隐藏这个事实,因为仅使用 enable_if 是不够的,您必须尝试访问其 ::type 字段,并且您必须以触发 SFINAE 的方式这样做。但实际上,我认为 SFINAE 不会起作用,因为必须访问“this”,而当它不可用时,这不是 SFINAE 问题。我可能是错的,但我看不到解决这个问题的方法。
      • @Noah:也许您应该仔细阅读,仔细查看那里的“(至少直接)”部分。 enable_if 允许您间接使用它。我承认我不确定 SFINAE 是否会为此工作(这就是我说“可能”的原因),但我仍然不确定它不能。
      • 好吧,正如我所说,enable_if 不允许您间接使用 SFINAE。当您调用 enable_if 时,您实际上是在直接使用它。 enable_if 元函数中没有任何 SFINAE;这只是一个微不足道的结构。所有 SFINAE 都是由编写客户端代码的人在调用站点完成的。 enable_if 只是一个很好的解释性名称,它使 SFINAE 代码的目的更易于理解。这与将 int 传递给 template <typename t> T::type f();</typename> 没有什么不同
      • SFINAE 如何帮助检测局部变量?
      【解决方案4】:

      受到唯我论的启发,但在实现上稍微简单一些:

      class Widget { 
        protected: 
        ::myDebuggingClass myDebuggingClass(char const* file, char const* function, int line) {
          return ::myDebuggingClass(file, function, line, this);
        }
        // ...
      

      这消除了对阴影变量的需要;它依赖于简单的类名查找规则。

      【讨论】:

        【解决方案5】:

        我能想到的唯一方法是定义一个全局变量:

        Widget * this = NULL;
        

        如果它甚至可以编译(我有疑问,但没有编译器来测试它),成员函数将使用最近的作用域变量(真正的his 指针),而其他一切都将得到一个空值。每个人都很高兴(可以这么说......)

        【讨论】:

          【解决方案6】:

          你可以使用弱引用来检测变量或函数是否存在。 例如: 检测是否存在:

          int a 属性((弱)); 如果一个) 存在 别的 不存在

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2014-09-08
            • 2014-06-23
            • 2016-12-28
            • 2019-05-08
            • 2013-11-13
            • 2017-08-05
            相关资源
            最近更新 更多