我可以区分一个或多个参数吗?

Can I differentiate between one and multiple arguments?

本文关键字:参数 我可以区 一个      更新时间:2023-10-16

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

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

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

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

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

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

它的主要用途是从可变数量的参数中推导出可变数量的类型;你可以将它们全部存储在某个地方(如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

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

另一个例子,来自最近的一个问题,我递归地定义了一个数据结构(简短而简单,可以阅读(: 使用可变参数模板的多键映射

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

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

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

对于一般的函数,一直支持可变参数函数(例如 printf (。

这对某些人来说似乎很愚蠢 - 但我有一公吨的 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);
}