一个Debug-Print函数来控制它们
One Debug-Print function to rule them all
我的情况是,我有几个不同的结构在我的代码,我想打印到控制台。
三个例子(几百个):
typedef struct ReqCntrlT /* Request control record */
{
int connectionID;
int dbApplID;
char appDescr[MAX_APPDSCR];
int reqID;
int resubmitFlag;
unsigned int resubmitNo;
char VCIver[MAX_VCIVER];
int loginID;
} ReqCntrlT;
//---------------------------------------------
typedef struct /* Connection request data block */
{
char userID[MAX_USRID];
char password[MAX_PWDID];
} CnctReqDataT;
//---------------------------------------------
typedef struct {
char userID[LOGIN_MAX_USERID];
char closure;
int applVersion;
int authorizationDataLength;
void *authorizationData; } LoginReqDataT;
所以我想要的,是一个调试函数,简单地接受一个结构体作为参数,并提出结构体的所有成员,如下:
LoginReqDataT* foo = new LoginReqDataT;
foo->applVersion = 123;
//...
debugPrintMe(foo);
CnctReqDataT* bar = new CnctReqDataT;
strcpy(bar->userID, "123");
strcpy(bar->password, "mypwd");
debugPrintMe(bar);
我现在拥有的是一个无尽的函数,它做的事情是这样的:
template <class T>
void debugPrintMe(T myvar)
{
if (!DEBUG) return;
if (typeid(T) == typeid(ReqCntrlT*))
{
ReqCntrlT* r = (ReqCntrlT*)myvar;
cout << "reqControl: " << endl
<< "tconnectionID: " << r->connectionID << endl
<< "tdbApplID: " << r->dbApplID << endl
//...
<< "tloginID: " << r->loginID << endl << endl;
}
else if (typeid(T) == typeid(CallBkAppDataT*))
{
CallBkAppDataT* c = (CallBkAppDataT*)myvar;
cout << "appData: " << endl
<< "tappRespBlockSize " << c->appRespBlockSize << endl
//...
<< "tstreamType: " << c->streamType << endl << endl;
}
//... and so on
}
是否有更优雅的方法来做到这一点?
是的,肯定有一种更优雅的方法(... else if (typeid(T) == ...
?恶心!)你可以用operator <<()
来表示struct
。这使得你的debugPrintMe()
函数很好和通用,也允许你流你的结构到cout
, cerr
,一个记录器,一个ostringstream
,…
这里有一个例子让你开始:
std::ostream& operator <<(std::ostream& os, const ReqCntrlT& r)
{
os << "reqControl"
<< "ntconnectionID: " << r.connectionID
<< "ntdbApplID: " << r.dbApplID
<< "ntappDescr: " << r.appDescr
<< "ntreqID: " << r.reqID
<< "ntresubmitFlag: " << r.resubmitFlag
<< "ntresubmitNo: " << r.resubmitNo
<< "ntVCIver: " << r.VCIver
<< "ntloginID: " << r.loginID
<< 'n';
return os;
}
template <class T>
void debugPrintMe(const T& myvar)
{
if (DEBUG)
{
std::cout << myvar << std::endl;
}
}
int main()
{
ReqCntrlT r;
// [...]
debugPrintMe(r);
return 0;
}
我认为这在没有内置自省的语言中是不容易做到的,所以你最好为每个结构重载operator<<
,以便将它们打印到ostream。
比起在typeid
上进行分支,我会使用一个非常基本的c++特性,它没有任何运行时开销:函数重载!既然你写的代码是要打印函数的,那就把它分成单独的函数:
void debugPrintMe(ReqCntrlT const& r){
// ...
}
void debugPrintMe(CallBkAppDataT const& c){
// ...
}
// others
既然您已经愿意使用模板函数来检查typeid(T),那么您可能希望只专门化TheOneTrueDebugFunction的实现:
template <class T>
void debugPrintMe(const T& myvar);
template <>
void debugPrintMe< ReqCntrlT* >(T)
{
// implementation to print debug messages
}
template <>
void debugPrintMe< CallBkAppDataT* >(T)
{
// implementation
}
正如您所注意到的,您必须使用typeid(T)==typeid(XYZ*)
进行游戏,以使其打印正确的类型,以响应类型是Struct
, Struct*
, const Struct *
等等。您将需要探索使用更通用的类型特征来避免更多的重复代码。
相关文章:
- 控制允许动态运行c++的并发操作数
- 从控制台中删除最后打印的元素
- 是否可以使用if constexpr删除控制流语句
- 无法在windows控制台中为C++程序提供必要的输入
- 控制到达非空函数clang(-Wreturn-type)的末尾
- 可视化C++:发布模式的运行时库作为'Multi-threaded Debug DLL'
- 查找 GCD:并非所有控制路径都返回值
- 通过 API 控制 DJI 相机
- 禁止在控制台上记录谷神星
- 犰狳的 print() 方法和 cout 在从 Rcpp 调用时顺序不一致
- 是否可以使用一个类来控制 C++ 中另一个类的对象?(阿杜伊诺)
- 如何删除列出的"QGraphicsPathItem"对象以控制进程内存使用情况?
- LNK1104:无法打开libpjproject-i386-Win32-vc14-Debug-Static.lib
- 在 Boost::fiber 中引发的BOOST_ASSERT故障 Visual Studio "Debug" 构建
- 我在 C++ 代码中遇到错误警告:控制到达非空函数 [-Wreturn 类型] 的末尾
- C++ Python 模块在 Blender 中崩溃,但在 Python 控制台中不会崩溃
- wx通用目录控制错误"wxTheFileIconsTable was nullptr"
- main() 中的 std::cout 在调试期间不会在调试控制台中打印任何内容
- Cython通过浮点数的最快方式,用于高频控制回路
- 一个Debug-Print函数来控制它们