1

C++11 或 C++14 中是否有任何新工具可以让我们停止使用:

TRACE0("one-string-no-args");  

TRACE("formatting string with one-or-more args", arg1, arg2, etc);  

此类函数必须按名称进行区分,因为据我所知,重载无法区分零附加参数情况和一个或多个参数情况。

这对于printf样式接口当然很重要,能够知道不再有参数意味着您可以通过不尝试将格式化字符串解释为格式化字符串而仅将其解释为最终输出字符串来避免一类错误。

4

3 回答 3

3

您可能只是不知道该功能的名称:可变参数模板

它的主要用途是从可变数量的参数中推断出可变数量的类型;您可以将它们全部存储在某个地方(例如std::make_tuple()),或者只是打开参数来使用它们。

这是一个基本用法:

void print() {}

template<class Head, class... Tail>
void print(Head h, Tail... t)
{
    cout << h << endl;
    print(t...);
}

int main()
{
    print(3, "hello", 4.5);
}

在此处查看实际操作:http: //ideone.com/VA7YGK

正如您所看到的,它看起来像函数式编程(因为它是!),在其中您匹配将参数列表拆分为头部和尾部的规则,然后用少一个元素调用自身。

另一个例子,来自最近的一个问题,我在其中递归地定义了一个数据结构(简短且简单易读):Multikey map using variadic templates

构造std::thread函数是另一个例子,一旦它开始在生成的线程中运行,它需要可变数量的参数将它们提供给函数;几乎 C++11 中与函数交互的所有新事物(例如std::function)都使用可变参数模板,因此它们可以接受任意数量的任何类型的参数。std::tuplestd::make_tuple()并且std::tie()还可以利用它。

在网上搜索你会发现很多更高级的用法。特别注意参数扩展的规则,完善转发。

于 2013-10-08T17:33:39.700 回答
0

对于TRACE宏(通常包含在 Microsoft 的调试宏中),不,该语言将没有处理预处理器宏的“新”方法(实际上与以前相同)。

对于一般函数,始终支持可变参数函数(例如printf)。

于 2013-10-08T17:11:20.430 回答
0

这对某些人来说可能看起来很愚蠢——但我有大量的 C 风格的 printf 代码需要维护。

我们可以使用 boost 的格式化库来重建它,也许我们会在这些日子里得到它。然而,与此同时,仅仅能够区分一个论点,或者一个+一个或多个论点是向前迈出的一大步。

https://stackoverflow.com/users/365496/bames53指出这是可能的,并且它似乎可以工作(在代码膨胀方面可能会付出一些代价,并且需要注意的是,这仍然是 printf 土地及其所有陷阱)。

这是一个在 MFC/C++ 中完成工作的简单示例:

bool Write(const wchar_t * pszText);
template <typename T> bool Write(const wchar_t * pszFormat, T, ...);

Write 不需要(也不应该)调用等效的 vwsprintf,而 Write<> 这样做是为了在将输出字符串传递给 Write 之前构建输出字符串。

十分优雅。消除了仅提供第二个接口的问题(如果您的一个字符串碰巧有一个意外的 printf 格式说明符,则会出现 printf 问题),或者强制客户端指定 Write() 与 WriteFormat() 或类似地执行在调用 Write() 之前本地构造字符串。

下面是用 Write 定义的 Write<>:

template <typename T> bool SimpleTextFile::Write(const wchar_t * pszFormat, T, ...)
{
    va_list arglist;
    va_start(arglist, pszFormat);
    CStringW buffer;
    buffer.FormatV(pszFormat, arglist);
    va_end(arglist);
    return Write(buffer);
}
于 2014-01-30T14:28:17.313 回答