完美转发参数包:转换参数而不扩展?

perfect foward a parameter pack: convert args without expansion?

在单元测试中,我试图实现更实用的代码并简化 class 函数调用,例如:

std::wstring widestr = std::wstring(o.Descr.begin(), o.Descr.end()); //o.Descr is string
wchar_t message[100];
swprintf(message, 100, L"size: %d", size);
Logger::WriteMessage(message);

进入:

Logger::WriteMessage(Message(L"string: %d", widestr.c_str()));

使用:

template<typename... T>
wchar_t* Message(T &&... args)
{
    wchar_t message[100];
    swprintf(message, 100, forward<T>(args)...);
    return message;
}

但输出不同:

而不是

1。我首先做的是正确的事吗?我想念什么?

2。理想情况下,我想写类似 (c#):

的东西
$"size:{size}".ToLogMessage();

我想我不能用 c++{11,14,17}。你确认吗?

Logger::WriteMessageMicrosoft.VisualStudio.TestTools.CppUnitTestFramework 的一部分,我无法更改它。

主要问题是你没有展开包:

template <typename... T>
wchar_t* Message(T &&... args)
{
    wchar_t message[100];
    swprintf(message, 100, forward<T>(args)...);
    return message;
}

但是,您还 return 悬挂指针,这是个大问题。

最终,如果 Logger::WriteMessage 必须 接受一个指针,您将不得不在实用程序中包含所有三行代码。也许像:

template <typename... T>
void WriteLogMessage(T &&... args)
{
    wchar_t message[100];
    swprintf(message, 100, forward<T>(args)...);
    Logger::WriteMessage(message);
}

然后只是:

WriteLogMessage(L"size: %d", size));

现在我要请你考虑一下 Logger::WriteMessage 是否应该首先自己做这一切。

一旦你开始了,你可以考虑从 swprintf 切换到更像 C++ 的东西,这样你就不需要依赖一些任意的最大缓冲区大小。但是,使用 stringstreams 和字符串并不是世界上最有效的事情,因此您还可以考虑执行 swprintf 两次:一次使用 nullptr 输出只是为了获得结果字符串的大小,然后再次实际将其放入大小正确的 wchar_t 数组中……

……不幸的是,这只有 snprintf 才有可能;对于宽字符串,您必须反复尝试使用越来越大的缓冲区,直到 return 值表明您提供的缓冲区终于足够大。呃.