完美的参数包:无需扩展即可转换args?

时间:2019-01-04 13:44:17

标签: c++ c++11 functional-programming perfect-forwarding

在单元测试中,我试图获得功能更强大的代码,并简化诸如以下的函数调用类:

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;
}

但是输出是不同的:

Bad output

代替

The output I want

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

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

$"size:{size}".ToLogMessage();

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

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

1 个答案:

答案 0 :(得分:1)

主要问题是您没有扩展包:

time                        ticks
2019-01-04 14:14:59         3575
2019-01-04 13:14:59         3575
2019-01-04 12:14:59         3552
2019-01-04 11:14:59         3560
2019-01-04 10:14:59         3575

但是,您还返回了一个悬空的指针,这是一个大问题。

最终,如果template <typename... T> wchar_t* Message(T &&... args) { wchar_t message[100]; swprintf(message, 100, forward<T>(args)...); return message; } 必须接受一个指针,则必须将所有三行都包装在实用程序内。也许吧:

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切换到更类似于C ++的方式,这样您就不必依赖某些任意的最大缓冲区大小了。但是,使用字符串流和字符串并不是世界上最高效的事情,因此您也可以考虑执行两次swprintf:一次使用swprintf输出只是为了获得结果字符串的大小,然后再次将其实际放入大小正确的nullptr数组中……

…除非不幸的是,这仅适用于wchar_t;对于宽字符串,您必须使用越来越大的缓冲区重复尝试,直到返回值表明您提供的缓冲区最终足够大为止。 gh。