我应该如何删除可变参数函数?

时间:2018-11-09 11:13:36

标签: c++ variadic-functions

我读到可变参数函数不是很好的编码。

我有一个非常老的框架,其中包含一些可变参数函数,我想删除保留调试功能的可变参数。

DEBUG(wchar_t* text, ...)

此调试函数使用相同的字符串sintaxis%d,%f ...等调用类似printf的函数。

什么是正确的方法?

3 个答案:

答案 0 :(得分:2)

由于您标记了问题c++,因此可以基于c++流创建新的类/函数-甚至可能更改“旧”系统以使用新系统。然后随着时间的推移迁移到该系统,也许在某个时候您可以摆脱旧版本(在您的情况下为“ DEBUG”)。

答案 1 :(得分:1)

令人惊讶的是,我建议保留调试功能,除非您愿意将整个接口更改为IO(即流)的C ++方式。如果要使用printfprintf语法,请原样使用。否则,将其完全现代化。

例如,让我们让您的实现始终如一:

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*CC++,然后更改为:

template <class... Args>
auto dbg(const std::string& fmt, const Args&... args)
{
    printf(fmt.c_str(), args...);
}

然后您意识到printfCC++,现在的选择是摆脱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_liststd::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