我正在尝试创建一个简单的类似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
我认为nullstream
类型的东西最适合发布模式定义:
class nullstream{};
template <typename T>
nullstream& operator<<(nullstream& ns, T)
{
return ns;
}
目前主要有:
#include "Debug.h"
#include <iostream>
int main()
{
Debug(0) << "Running debug version of CAKE." << std::endl;
}
使用gcc 4.5.1发出以下错误:
在成员函数'Debug&amp; CAKE_Debug :: operator&lt;&lt;(T)':在';'之前的预期primary-expression令牌(指向
std::cout << T;
行)在函数'int main(int,char **,char **)'中:在'&lt;&lt;'之前的预期unqualified-id令牌
我确信这很简单,但我发现的所有常规模板信息都没有。谢谢你的帮助!
如果您需要更多信息,请询问。
答案 0 :(得分:6)
你的nullstream类没有整数构造函数。这意味着当你#define 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
};
现在,您的类在任何环境中的外观和行为都相同,但只有在定义了_DEBUG时才输出。我还修复了你试图输出类型的错误。
答案 1 :(得分:5)
其他人指出了普通物体的错误。
template<typename T>
Debug& operator<<(T const& value)
{
if ( m_output )
{
std::cout << value;
}
return *this;
}
但是你还需要一种输出std :: endl和其他操纵器的方法。由于上面的模板将无法正确处理这些。为此,您需要一个操作符来处理操作流的函子(即所有的iomanipulator(如std :: endl))。
// 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;
}
答案 2 :(得分:2)
你应该写点像
operator<<(const T &t)
并在此方法中使用t
代替T
(这是类型)。
答案 3 :(得分:2)
错误在这里:
template<typename T>
Debug& operator<<( T )
{
if ( m_output )
{
std::cout << T;
return *this;
}
else
return *this;
}
您无法输出类型,您必须输出一个对象。正确的代码:
template<typename T>
Debug& operator<<( T value)
{
if ( m_output )
{
std::cout << value;
}
return *this;
}
答案 4 :(得分:1)
template<typename T>
Debug& operator<<( T )
这个签名是错误的;你有一个<<
参数的类型,但不是它的名字。然后,您需要在T
std::cout << T;
答案 5 :(得分:0)
已经指出使用cout << T;
的问题(您需要提供一个对象实例,而T
是一种类型)。
当你解决这个问题时,你会遇到至少一个问题:Debug(0)
创建一个临时对象。要将其作为参数传递给nullstream operator<<
,则需要使用nullstream const &
而不是nullstream &
作为参数。
答案 6 :(得分:0)
...这将导致l / rvalue问题。如果需要全局Debug输出对象,只需遵循std::cout
模式。否则,请说:
Debug tDbg(tLevel);
tDbg << "Message" << std::endl;