C++ 我可以区分一个参数和多个参数吗?
C++11或C++14中是否有任何新功能允许我们停止使用:C++ 我可以区分一个参数和多个参数吗?,c++,c++11,printf,variadic-functions,C++,C++11,Printf,Variadic Functions,C++11或C++14中是否有任何新功能允许我们停止使用: TRACE0("one-string-no-args"); 及 此类函数必须按名称进行区分,因为据我所知,重载无法区分零附加参数情况和一个或多个参数情况 当然,这对于printf风格的接口很重要,在这种接口中,能够知道不再有参数意味着您可以通过不尝试将格式化字符串解释为格式化字符串,而仅将其解释为最终输出字符串来避免一类错误。对于跟踪宏(通常包括在Microsoft的调试宏中),不,该语言将没有处理预处理器宏的“新”方法(实际上与
TRACE0("one-string-no-args");
及
此类函数必须按名称进行区分,因为据我所知,重载无法区分零附加参数情况和一个或多个参数情况
当然,这对于
printf
风格的接口很重要,在这种接口中,能够知道不再有参数意味着您可以通过不尝试将格式化字符串解释为格式化字符串,而仅将其解释为最终输出字符串来避免一类错误。对于跟踪
宏(通常包括在Microsoft的调试宏中),不,该语言将没有处理预处理器宏的“新”方法(实际上与以前相同)
对于一般功能,始终支持可变功能(例如,
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);
}
void print(){}
模板
无效打印(头h、尾…t)
{
cout这对某些人来说似乎很愚蠢,但我有一公吨C风格的printf代码要维护
我们可以使用boost的格式库来重新构建它,也许有一天我们会实现。然而,与此同时,仅仅能够区分一个参数,或者一个+一个或多个参数是一个巨大的进步
注意,这样做是可能的,而且它似乎可以工作(在代码膨胀中可能会付出一些代价,并且需要注意的是,这仍然是printf-land的所有陷阱)
下面是一个在MFC/C++中完成其工作的简单示例:
bool Write(const wchar_t * pszText);
template <typename T> bool Write(const wchar_t * pszFormat, T, ...);
bool Write(const wchar_t*pszText);
模板布尔写入(常量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);
}
template bool SimpleTextFile::Write(常量wchar\u t*pszFormat,t,…)
{
va_列表arglist;
va_启动(arglist,pszFormat);
CStringW缓冲区;
FormatV(pszFormat,arglist);
va_end(arglist);
返回写(缓冲区);
}
void trace(string);
vstemplate void trace(string,Ts…)
对于编译器来说是完全可以区分的。是的,可变模板就是这样做的。如果您不知道名称,这里就是。一个“安全”打印函数是可变模板的典型介绍性示例。顺便说一句,我从未使用过它,但是如果你真的想把它带到下一个级别,boost有一个非常酷的功能Trace看起来像一个宏“这类函数必须按名称区分,因为据我所知,重载无法区分零附加参数情况和一个或多个参数情况。”据我所知,C++98中的重载在区分具有一个参数的函数和具有两个或多个参数的函数方面没有问题:void foo(int);模板void foo(int,T,…);
(当然,只有当您希望第二个参数的类型与varargs尽可能不同时,才需要模板。)
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);
}