4

我需要为一个项目使用FormatMessage(),但我不喜欢它可怕的界面。有谁知道一个外观可以整理它,同时仍然允许替换参数?

我刚刚阅读了FastFormat 介绍的第二部分,并且正在考虑为FormatMessage()编写一个扩展(或者询问FastFormat项目团队是否有一个在工作中),但我很想尽快得到一些东西,所以如果那里还有其他像样的东西,我可能会抓住它。

我想要的是能够编写代码,例如:

HINSTANCE netevent = ::LoadLibrary("netevent.dll");
std::string msg = LookupError(netevent, EVENT_SERVICE_START_FAILED_II,
    "child-svr", "parent-svr", "ship happens");
::puts(msg.c_str());

这将给出结果:

The child-svr service depends on the parent-svr service which failed to start be cause of the following error:
ship happens

我构建的当前包装器具有接口:

std::string LookupError(HINSTANCE hinst, DWORD id, ...);

这有两个问题:

  • 它不是类型安全的,因为很容易传递任何类型 - int, std::string, void*-const char*
  • 参数的数量很容易与表示错误的格式字符串所需的数量不匹配

鉴于FastFormat在类型安全方面的能力,我想知道是否有办法遵循其处理FormatMessage()的机制。

4

2 回答 2

1

由于编译器无法检查要插入格式字符串的参数数量,因此在编译时不可能使其真正成为类型安全的。

您可以通过对不同数量的插入参数进行一些重载,然后使用灵活的诸如boost::any. 所以两个参数的重载将是:

std::string FormatMessage(HINSTANCE hinst, DWORD id, const boost::any &arg1, const boost::any &arg2);

当您从 中检索值时arg1,如果您尝试获取错误的类型,boost 会抛出异常,因此您只需检查格式字符串并尝试从每个参数中获取所需的类型。

或者,您可以使用模板和 std::ostringstream(或 boost::lexical_cast)来获得非常灵活的版本;再次会有重载以允许参数数量变化,所以这里是单参数版本:

template <class TArg1>
std::string FormatMessage(HINSTANCE hinst, DWORD id, const TArg1 &arg1)
{
    std::ostringstream arg1Stream;
    arg1Stream << arg1;
    std::string arg1String = arg1Stream.str();

    DWORD_PTR argArray = reinterpret_cast<DWORD_PTR>(arg1String.c_str());

    // ... etc
}

这样,只要传递的类型可以流式传输,您就可以从每个参数中获取一个字符串,只要格式字符串只需要插入字符串,就不需要其他任何东西。

于 2009-05-10T11:42:02.040 回答
0

C++ 格式库允许格式化与返回的错误代码相对应的本机 Windows 错误消息GetLastError()和与 .给出的错误相对应的 POSIX 错误消息errno。例如:

// This throws a WindowsError with the description
//   cannot open file 'madeup': The system cannot find the file specified.
// or similar (system message may vary).
const char *filename = "madeup";
LPOFSTRUCT of = LPOFSTRUCT();
HFILE file = OpenFile(filename, &of, OF_READ);
if (file == HFILE_ERROR)
  throw fmt::WindowsError(GetLastError(), "cannot open file '{}'", filename);

FormatMessage使用API 函数获取 Windows 错误消息。您还可以格式化fmt::format_windows_error不会引发异常的错误消息。有关详细信息,请参阅系统错误。

免责声明:我是 C++ 格式的作者

于 2015-02-19T01:54:50.263 回答