【问题标题】:Macro function not expanding as expected宏功能未按预期扩展
【发布时间】:2019-10-04 11:39:47
【问题描述】:

编辑可能的重复链接无助于解决问题。

下面是cmets的最小可编译代码,问题是ERR_INFO宏导致在宏函数LOG_IF_FAILED中扩展HRESULT˙参数时出现问题

我确信这个问题是微不足道的,但调试宏是一场噩梦。

#define UNICODE
#include <Windows.h>
#include <comdef.h>
#include <iostream>
#include <cwchar>


void DebugLogTrace(PCTSTR format_string, ...)
{
    // implementation not important
}

// Writes a sprintf-formatted string to the logging file.
#define TRACE(...) DebugLogTrace(__VA_ARGS__)

#ifdef UNICODE
// Show only file name instead of full path wide version
#define FILENAME (std::wcsrchr(TEXT(__FILE__), L'\\') ? std::wcsrchr(TEXT(__FILE__), L'\\') + 1 : TEXT(__FILE__))

// Wide string function name
#define FUNCNAME __FUNCTIONW__

// boilerplate macro
#define ERR_INFO FILENAME, FUNCNAME, __LINE__

// Log HRESULTs if failed.
#define LOG_IF_FAILED(file_name, func_name, line, hr) if (FAILED(hr)) \
    { TRACE(TEXT("%s %s %i %s"), file_name, func_name, line, _com_error(hr).ErrorMessage()); }
#else

// ANSI versions here ...

#endif // UNICODE

int main()
{
    HRESULT hr = CoInitializeEx(nullptr,
        COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);

    // Here hr is not inserted into expansion
    // ERR_INFO macro is causing problems somehow
    LOG_IF_FAILED(ERR_INFO, hr);

    // This works however
    LOG_IF_FAILED(FILENAME, FUNCNAME, __LINE__, hr);

    return 0;
}

【问题讨论】:

  • LOG_IF_FAILED 接受 4 个参数,但您只提供 2 个?
  • @AlanBirtles 第一个参数是一个宏,应该扩展为 3 个参数。产生 4 个参数,除了第 4 个参数被忽略之外,其他参数都有效。
  • 恐怕宏不能这样工作
  • @AlanBirtles 我在 VS 的工具提示中看到 ERR_INFO 宏扩展为 3 个参数,只有第 4 个 HRESULT 没有扩展。有其他类似的宏,它们可以工作。

标签: c++ macros


【解决方案1】:

LOG_IF_FAILED(ERR_INFO, hr) 应该会导致类似以下内容:
error: macro "LOG_IF_FAILED" requires 4 arguments, but only 2 given

这可以通过多一层间接来解决。

LOG_IF_FAILED 重命名为其他名称,比如LOG_IF_FAILED_
然后添加#define LOG_IF_FAILED(...) LOG_IF_FAILED_(__VA_ARGS__)

编辑:

由于某种原因,这不适用于 MSVC 预处理器。如果您使用的是 MSVC,LOG_IF_FAILED 应定义为:

#define EMPTY
#define LOG_IF_FAILED(...) LOG_IF_FAILED_ EMPTY (__VA_ARGS__)

【讨论】:

  • 我刚刚尝试过,现在main 中的 2 个宏都不起作用。
  • 你这个骗子!这确实有效,非常感谢!你能解释一下这是如何工作的,有什么诀窍吗?我们能否得出结论,MSVC 预处理器违反了标准?
  • 哦,我明白了,msvc 无法扩展 __VA_ARGS__ 你的解决方案与 #define EXPAND(x) x #define LOG_IF_FAILED(...) LOG_IF_FAILED_ EXPAND((__VA_ARGS__)) 相同
  • @santoshdhanawade 谢谢我现在明白了这个问题,这只是我讨厌微软的另一个原因。
猜你喜欢
  • 2020-05-26
  • 1970-01-01
  • 2013-04-20
  • 2021-11-13
  • 2013-08-29
  • 1970-01-01
  • 2020-04-28
  • 2021-08-27
  • 1970-01-01
相关资源
最近更新 更多