我读到可变参数函数不是很好的编码。
我有一个非常老的框架,其中包含一些可变参数函数,我想删除保留调试功能的可变参数。
DEBUG(wchar_t* text, ...)
此调试函数使用相同的字符串sintaxis%d,%f ...等调用类似printf的函数。
什么是正确的方法?
答案 0 :(得分:2)
由于您标记了问题c++
,因此可以基于c++
流创建新的类/函数-甚至可能更改“旧”系统以使用新系统。然后随着时间的推移迁移到该系统,也许在某个时候您可以摆脱旧版本(在您的情况下为“ DEBUG”)。
答案 1 :(得分:1)
令人惊讶的是,我建议保留调试功能,除非您愿意将整个接口更改为IO(即流)的C ++方式。如果要使用printf
和printf
语法,请原样使用。否则,将其完全现代化。
例如,让我们让您的实现始终如一:
void dbg(char* txt, ...)
{
va_list args;
va_start(args, txt);
vprintf(txt, args);
va_end(arts);
}
是的,有一些选项可以摆脱可变参数,但是如果您要保留printf
系列语法,则这样做有0收益:
template <class... Args>
auto dbg(const char* fmt, const Args&... args)
{
printf(fmt, args...);
}
然后,您意识到char*
比C
多C++
,然后更改为:
template <class... Args>
auto dbg(const std::string& fmt, const Args&... args)
{
printf(fmt.c_str(), args...);
}
然后您意识到printf
比C
多C++
,现在的选择是摆脱printf
并完全废弃。
这个问题How to make a variadic macro for std::cout?向您展示了一种方法,如果您仍然在函数上进行设置:
template<typename ...Args>
void log(Args && ...args)
{
(std::cout << ... << args);
}
另一种选择是做这样的事情:
log << "this is the " << i << " log";
但是要在末尾添加换行符并不是一件容易的事。
最后,我认为最好的解决方案是使用日志记录库。
答案 2 :(得分:1)
我同意@bolov的建议,保留调试功能不变。
但是,您可能会使用std::initializer_list
和std::variant
(自C ++ 17起)类型。
下面是一个小的示例,该示例尚未处理格式说明符,但可以给出一些想法以发展该方法。
#include <iostream>
#include <cstdlib>
#include <variant>
typedef std::variant<std::string, int, float, bool> DebugOutParam;
std::ostream& operator << (std::ostream& os, const DebugOutParam& v)
{
if (std::holds_alternative<std::string>(v))
os << std::get<std::string>(v);
else if (std::holds_alternative<int>(v))
os << std::get<int>(v);
else if (std::holds_alternative<float>(v))
os << std::get<float>(v);
else if (std::holds_alternative<bool>(v))
os << (std::get<bool>(v) ? "true" : "false");
else
os << "?Unsupported?";
return os;
}
typedef std::initializer_list<DebugOutParam> DebugOutParams;
void dbg(std::string fmt, DebugOutParams l)
{
std::cout << fmt << ": ";
for (DebugOutParams::const_iterator it = l.begin(); it != l.end(); it++)
{
DebugOutParam v = *it;
std::cout << (it == l.begin() ? "" : ", ") << v;
}
std::cout << std::endl;
}
int main()
{
dbg("Test", {123, std::string("456"), true, static_cast<float>(456.789)});
}
输出
Test: 123, 456, true, 456.789