我读到变量参数函数不是很好的编码。
我有一个非常旧的框架,里面有一些变量参数函数,我想删除保留调试函数的变量参数。
DEBUG(wchar_t* text, ...)
此调试函数使用相同的字符串sintaxis%d,%f调用类似printf的函数。。。等
什么应该是正确的方法?
由于您将问题标记为c++
,因此您可以基于c++
流创建一个新的类/函数,甚至可以将"旧"系统更改为使用新系统。然后随着时间的推移迁移到那个系统,也许在某个时候你可以摆脱旧的(在你的情况下是"调试"(。
令人惊讶的是,我建议保持调试功能不变,除非您愿意将整个接口更改为IO的C++方式,也就是流。如果你要使用printf
和printf
语法,那就顺其自然吧。
例如,让我们停留在您的实现中:
void dbg(char* txt, ...)
{
va_list args;
va_start(args, txt);
vprintf(txt, args);
va_end(arts);
}
是的,有一些选项可以去掉variadic,但如果你要保留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
并完全废弃它。
这个问题如何为std::cout制作一个可变宏?向你展示了一种方法,如果你仍然设置了一个功能:
template<typename ...Args>
void log(Args && ...args)
{
(std::cout << ... << args);
}
另一种选择是制作这样的东西:
log << "this is the " << i << " log";
但让它在末尾添加一行换行并不是一件小事。
最后,我认为最好的解决方案是使用日志库。
我同意@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