C++ 带有模板化运算符的条件调试输出类<&书信电报;

C++ 带有模板化运算符的条件调试输出类<&书信电报;,c++,templates,debugging,C++,Templates,Debugging,我正在尝试创建一个简单的qDebug类,可以用来在调试模式下输出调试消息,具体取决于调用应用程序时传递的调试级别。我喜欢QDebug类的易用性(它可以用作std::cerr,在发布模式下编译时会消失)。到目前为止,我有: #ifdef DEBUG static int CAKE_DebugLevel; class Debug { Debug( int level ) : m_output( level <= CAKE_DebugLevel ) {}

我正在尝试创建一个简单的qDebug类,可以用来在调试模式下输出调试消息,具体取决于调用应用程序时传递的调试级别。我喜欢QDebug类的易用性(它可以用作std::cerr,在发布模式下编译时会消失)。到目前为止,我有:

#ifdef DEBUG
    static int CAKE_DebugLevel;

    class Debug
    {
        Debug( int level ) : m_output( level <= CAKE_DebugLevel ) {}

        template<typename T>
        Debug& operator<<( T )
        {
            if( m_output )
            {
                std::cout << T;
                return *this;
            }
            else
                return *this;
        }
    private:
        bool m_output;
    };
#else // release mode compile
    #define Debug nullstream
#endif // DEBUG
目前我主要有:

#include "Debug.h"

#include <iostream>

int main()
{
    Debug(0) << "Running debug version of CAKE." << std::endl;
}
#包括“Debug.h”
#包括
int main()
{
调试(0)
模板

Debug&operator您应该编写如下内容

operator<<(const T &t)
运算符错误在这里:

template<typename T>
Debug& operator<<( T )
{
    if ( m_output )
    {
        std::cout << T;
        return *this;
    }
    else
        return *this;
}
模板

调试和操作员使用
cout的问题其他人指出了正常对象的错误

template<typename T> 
Debug& operator<<(T const& value)
{
    if ( m_output )  
    {  
        std::cout << value;  
    }  
    return *this;  
}
模板

Debug&operator您的nullstream类没有整数构造函数。这意味着当您#定义Debug nullstream时,编译器无法识别Debug(0)-这毫无意义。Debug不是接受参数的宏,如果用nullstream替换,则nullstream没有接受参数的构造函数。#以这种方式使用的define是非常错误的。您应该有如下内容:

#ifdef _DEBUG
static int CAKE_Debuglevel;
#endif

class Debug
{
    Debug( int level ) 
#ifdef _DEBUG
    : m_output( level <= CAKE_DebugLevel ) 
#endif
        {}

    template<typename T>
    Debug& operator<<( T t)
    {
        #ifdef _DEBUG
        if( m_output )
        {
            std::cout << t;
            return *this;
        }
        else
        #endif
            return *this;
    }
private:
#ifdef _DEBUG
    bool m_output;
#endif
};
\ifdef\u调试
静态int-u-Debuglevel;
#恩迪夫
类调试
{
调试(整数级)
#ifdef_调试

:m_输出(级别…这将导致l/R值问题。如果需要全局调试输出对象,只需遵循
std::cout
模式。否则,请说:

Debug tDbg(tLevel);
tDbg << "Message" << std::endl;
调试tDbg(tLevel);

tDbg Dang,愚蠢的编译器错误把我甩了…这修复了这个错误,但主要还是有一个问题,因为
与运算符不匹配这是一个完美的未来证明答案(参见我对Andre答案的评论)。我该怎么做,因为我真的不知道:(.它也可以模板化吗(实际上我只需要std::endl,但预见会更好,对吗)?谢谢这真的应该以输出类型为模板-如果你想改为wcout怎么办?@DeadMG:原始海报明确使用std::cout。但给我5分钟。马丁:谢谢你的建议,你已经得到了亚军的认可答案。这将如何扩展到发布版本中的代码?有没有比我建议的更好的方法谢天谢地,在发布版本中,它仍然提供相同的接口(关键),但没有一个构造函数或操作符做任何事情。这意味着,到目前为止,您将不会对正在发生的事情感到意外,这就是使用#define Debug nullstream得到的结果。如果我使用
#define Debug(integer)怎么办nullstream
?这不是最快的解决方案,开销最低吗?不是吗?nullstream没有做任何我的调试没有做的事情-我只是做了它,这样你就不会可怕地搞砸这个糟糕的宏系统,在这种情况下它是完全冗余的。你不需要nullstream,而且定义它是非常糟糕的做法,因为你可以。Y我们的nullstream与我在发布模式下的Debug相同。我的代码更干净,生成的代码也完全相同……还有一件事:为什么我不能让操作符查看为什么每个副本传递对象(操作日志),一个日志库,它把优化放在极点。@是的,我把参数改为const t,但是不知怎么回事,我总是试图保持const t和论点。谢谢链接,但是我使用起来有点太复杂了。我正在尽可能地学习C++。我自己,从而限制了外部依赖性。那段代码是否以任何方式涉及蛋糕?@einpoklum哈哈不,当我发现PHP of all things也与蛋糕有关时,我更改了名称。作为参考,我将其更改为使用C++11可变模板黑色巫毒魔法,以便有效地删除调试打印语句完全使用简单的宏定义。
template<typename T> 
Debug& operator<<(T const& value)
{
    if ( m_output )  
    {  
        std::cout << value;  
    }  
    return *this;  
}
// Use a typedef to make the code readable.
// This is a function pointer that takes a stream as input and returns the stream.
// This covers functions like std::endl
typedef std::ostream& (*STRFUNC)(std::ostream&);

D& operator<<(STRFUNC func)  // Inside the class
{
    if ( m_output )  
    {  
        // Apply the function
        func(std::cout);
    }
    // But return the debug object
    return *this;
}
#include <iostream>

#if defined(_DEBUG)
#define DEBUG_LOG_TEST_CONDITION        output
#define DEBUG_LOG_DEBUG_TEST_LEVEL(v)   (v) <= DebugCake::DebugLevel
#else
#define DEBUG_LOG_TEST_CONDITION        false
#define DEBUG_LOG_DEBUG_TEST_LEVEL(v)   false
#endif

template<typename C,typename T = std::char_traits<C> >
struct DInfo
{
    typedef std::basic_ostream<C,T>& (*StrFunc)(std::basic_ostream<C,T>&);
    static std::basic_ostream<C,T>& getDefault();
};

struct DebugCake
{
    static int DebugLevel;
};
template<typename C,typename T = std::char_traits<C> >
struct D
{

    D(int level)
        :stream(DInfo<C,T>::getDefault())
        ,output( DEBUG_LOG_DEBUG_TEST_LEVEL(level) )
    {}
    D(int level, std::basic_ostream<C,T>& s)
        :stream(s)
        ,output( DEBUG_LOG_DEBUG_TEST_LEVEL(level) )
    {}

    template<typename V>
    D& operator<<(V const& value)
    {
        // In release this is optimised away as it is always false
        if (DEBUG_LOG_TEST_CONDITION)
        {
            stream << value;
        }
        return *this;
    }

    D& operator<<(typename DInfo<C,T>::StrFunc func)
    {
        // In release this is optimised away as it is always false
        if (DEBUG_LOG_TEST_CONDITION)
        {
            func(stream);
        }
        return *this;
    }
    private:
       std::basic_ostream<C,T>&  stream;
       bool                      output;

};

template<>
std::ostream&  DInfo<char,std::char_traits<char>       >::getDefault()
{return std::cout; }

template<>
std::wostream& DInfo<wchar_t,std::char_traits<wchar_t> >::getDefault()
{return std::wcout; }

typedef D<char>    Debug;
typedef D<wchar_t> WDebug;
int DebugCake::DebugLevel = 4;


int main()
{
    Debug   debug(1);

    debug << "Plop" << std::endl;

    WDebug  debugWide(2);
    debugWide << L"WIDE" << std::endl;
}
#ifdef _DEBUG
static int CAKE_Debuglevel;
#endif

class Debug
{
    Debug( int level ) 
#ifdef _DEBUG
    : m_output( level <= CAKE_DebugLevel ) 
#endif
        {}

    template<typename T>
    Debug& operator<<( T t)
    {
        #ifdef _DEBUG
        if( m_output )
        {
            std::cout << t;
            return *this;
        }
        else
        #endif
            return *this;
    }
private:
#ifdef _DEBUG
    bool m_output;
#endif
};
Debug tDbg(tLevel);
tDbg << "Message" << std::endl;