我已经拥有一个使用大量couts的大型代码库。 我不能去改变所有现有的couts。 有什么我可以做的,现有的couts添加 FUNCTION , LINE 和时间信息以及需要在cout中打印的内容?换句话说,我可以覆盖cout以使用我的实现,它将打印字符串以及所有额外信息。 我愿意做其他任何事情,不一定要压倒一切......
也许我没有解释清楚.. 这就是我需要的。我已经有类似的东西了,
cout<<"This thing does not work";
&lt; - 在A.cpp中
cout<<"This thing does works but the problem is XYZ";
&lt; - 在B.cpp
cout<<"There was a problem reading JHI";
&lt; - 在C.cpp
。 。 等等..
在一个大型代码库中,我无法编辑所有现有的couts ..
我需要这些couts打印类似的东西..
cout<<"This thing does not work"<<__FUNCTION__<<__LINE__;
&lt; - 在A.cpp中
cout<<"This thing does works but the problem is XYZ"<<__FUNCTION__<<__LINE__;
&lt; - 在B.cpp
cout<<"There was a problem reading JHI"<<__FUNCTION__<<__LINE__;
&lt; - 在C.cpp
。
希望这会让它变得更清楚..我希望原始的couts可以自动转换(通过做一些技巧)转换,这样他们也可以打印这些额外的信息..
答案 0 :(得分:2)
(您的问题并不完全重复this,因为您还想输出行和源文件信息,àla__FILE__
和{{1这会产生重大影响;但是我觉得你的问题有点过于宽泛而且缺乏细节)
您可以使用GCC MELT(我已设计并实现)自定义最近的GCC编译器以执行您想要的操作。然后,您将编写一个额外的“优化通道”,它会神奇地转换您的__LINE__
...输出语句(在编译器内),通过使它们等效于builtin expressions > std::cout <<
....;您需要在Gimple级别进行适当的转换。
这可能不是一项微不足道的任务,因为您需要了解GCC内部表示的细节。因此,我并不完全确定它是值得的(除非你的代码库至少有五百万的源代码行,并且花费几周的时间来编写你的MELT定制是值得的。)
如果你能负担得起手动编辑每一条相关的行,像here这样的宏观方法可能更简单。
您可以将两者结合起来,使用MELT检测正确的行进行编辑,并将它们反馈到std::cout << __builtin_FILE () << ' ' << __builtin_LINE () << ' ' <<
脚本中,从而转换源代码以调用宏。
在内部,编译器可以处理某些内部表示,它是规范化 AST,甚至更简单(Gimple)。对于GCC,您希望转换
的内部表示sed
接近
的内部表示 extern "C" void testit(int x) {
if (x>0)
std::cout << "x=" << x << std::endl;
}
要理解 Gimple表示,请使用 extern "C" void transformed_testit (int x) {
if (x>0)
std::cout << __builtin_FILE() << ' ' << __builtin_LINE() << ' '
<< "x=" << x << std::endl;
}
进行编译;这是第一个函数的Gimple代码的 textual 转储(实际上,Gimple只是一个 in-memory 数据结构):
g++ -fdump-tree-gimple
因为您的源代码可能包含许多变体的输出,包括
void testit(int) (int x)
{
struct basic_ostream & D.21753;
struct basic_ostream & D.21754;
if (x > 0) goto <D.21751>; else goto <D.21752>;
<D.21751>:
D.21753 = std::operator<< <std::char_traits<char> > (&cout, "x=");
D.21754 = std::basic_ostream<char>::operator<< (D.21753, x);
std::basic_ostream<char>::operator<< (D.21754, endl);
goto <D.21755>;
<D.21752>:
<D.21755>:
}
或
std::cout << "x=" << x << std::endl;
或
using namespace std;
cout << "x=" << x << endl;
甚至
#define MY_LOG(Out) do{std::cout<<Out<<std::endl;} while(0)
MY_LOG("x=" << x);
(在上面的示例中,两行代码可能相距甚远,甚至在不同的文件中,例如某些头文件中的auto& output = std::cout;
output << "x=" << x << std::endl;
,并在某些实现文件中使用...但Gimple表示在所有情况下都非常相似)
因此,如果您能够花费至少两周的时间来解决问题,请尝试使用GCC MELT。否则,手动运行 某些#define MY_LOG
脚本,或者编写您的Emacs功能代码以交互方式编辑
也许你可能有
sed
然后你可以做
struct myoutputat {
const char*fil;
int lin;
myoutputat(const char*f, int l) : fil(f), lin(l) {};
std::ofstream& operator << (const char*msg) {
std::cout << f << ' ' << l << msg;
return std::cout;
}
}; // end of myoutputat
#define mycout myoutputat(__FILE__,__LINE__)
因此,您可以在mycout << "x=" << x << std::endl;
...后尝试#define cout mycout
;它可能会泄漏许多错误消息,您可以在其位置手动调整代码
PS。您可以通过私人电子邮件与我联系#define mycout
,但请提及您的问题的网址,提供更多详细信息:您的代码在做什么,它的源大小是什么,确切的编译器是什么你在用什么,你的雇主是什么?国家等......
答案 1 :(得分:1)
显而易见的解决方案是使用一些编辑器宏,例如vim's macros与grep -rnw 'directory' -e "cout <<"
配对,假设是Linux平台。
关于C ++,如果您在整个代码中使用cout
而不是std::cout
,那么可能的解决方案就是删除using namespace std
然后推出您自己的cout
函数 - 假设您没有其他代码,具体取决于std::
将会中断。
已将问题标记为重复的问题might contain an answer。