【问题标题】:Debug macro for C++ with variable arguments without the format string带有可变参数的 C++ 调试宏,没有格式字符串
【发布时间】:2011-12-25 11:26:10
【问题描述】:

是否可以编写一个可以接受可变数量参数并像这样扩展的宏:

quickdebug(a)   ->  cout << #a ": " << a;
quickdebug(a,b) ->  cout << #a ": " << a << #b ": "<< b;

如果没有,我是否可以至少打印所有参数而不提供格式字符串。例如

quickdebug2(a)   -> cout << a ;
quickdebug2(a,b) -> cout << a << " " << b ;

例如在 java 中,我可以编写一个提供类似功能的函数:

void debug(Object...args) 
{
  System.out.println(Arrays.deepToString(args));
}

【问题讨论】:

  • 在 Java 中你不能做到#a。所以这个比喻是不正确的。您可以使用 C++ 中的可变参数模板(或多个非可变参数模板)完成您在 Java 中所做的工作。
  • 我在 Java 中所做的是对 quickdebug2 的类比。并且使用可变参数模板,我不明白如何找出参数的大小和类型。我的意思是我也希望能够像这样使用它(我可以在 Java 中这样做):debug(42, "inner", 23.2)
  • “使用可变参数模板,我不明白如何找出参数的大小和类型”呵呵?这就是可变参数模板的用途。
  • printf variadic template in Wikipedia 就是一个例子。你的版本会是这样的:void quickdebug() { } template&lt;typename A, typename... B&gt; void quickdebug(A a, B... b) { std::cout &lt;&lt; a; quickdebug(b...); }

标签: c++ debugging macros variadic-functions


【解决方案1】:

通过使用覆盖 , 运算符的类:

class VariadicToOutputStream
{
public:
    VariadicToOutputStream(std::ostream& s, const std::string& separator = " ") : m_stream(s), m_hasEntries(false), m_separator(separator) {}
    template<typename ObjectType>
    VariadicToOutputStream& operator , (const ObjectType& v)
    {
        if (m_hasEntries) m_stream << m_separator;
        m_stream << v;
        m_hasEntries=true;
        return *this;
    }
    ~VariadicToOutputStream()
    {
        m_stream << std::endl;
    }

private:
    std::ostream& m_stream;
    bool m_hasEntries;
    std::string m_separator;
};

你可以这样写:

VariadicToOutputStream(std::cout) , 1, 0.5f, "a string";

然后可以用预处理器宏包装:

#define VARIADIC_TO_STDOUT(...)     VariadicToOutputStream(std::cout),__VA_ARGS__;

所以你可以写:

VARIADIC_TO_STDOUT(1, 0.5f, "a string");

添加 f.i. 会很容易。要在参数之间使用的分隔符字符串。

编辑:我刚刚添加了一个默认空格作为分隔符字符串。

【讨论】:

  • 感谢罗伯特的魔法。这可能是我见过的最酷的 C++ hack。冰雹! :)
  • @Nikhil:谢谢,很高兴我能帮上忙 :)
  • 我做了一个小改动:我为这个类创建了一个析构函数来打印一个新行。因此,返回时的每个宏调用最后都会打印一个新行。如果你愿意,你也可以在你的答案中编辑它=)
【解决方案2】:

可以制作一个可变参数的宏,从而采用可变数量的参数。语法类似于函数:

#define quickdebug(...) functiontocall("test", __VA_ARGS__)

在参数列表中最后一个命名参数之后列出的任何参数都将在__VA_ARGS__ 中列出,包括任何分隔逗号。

所以:quickdebug(1, 2, "123", 4.5) 变为 functioncall("test", 1, 2 , "123", 4.5)

但是在某些时候您需要使用这些参数,如果您没有格式字符串或其他指示参数类型的东西,这会变得非常困难。

问题在于,当从变量参数列表中读取变量时,您需要知道参数的类型,或者至少知道它的大小。如果我是你,我会选择不同的方法。

您可以在此处阅读有关可变参数宏的更多信息:http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-01
    • 2011-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多