以更好的方式提出问题:
拥有一个记录器C ++类,其中包含<<运算符重载以接受整数,字符串..
logR <<"Test"<<endl
现在endl被定义为宏
#define endl "\n\r"
现在在任何.cpp文件中,如果我包含了这个记录器类的头文件,我曾经因使用endl而得到编译错误。
找到一个修复此问题而不是定义宏endl,我重载运算符以接收endl()本身。 感谢有助于解决问题的投入。
答案 0 :(得分:5)
来自标准N4687:
20.5.4.3.2宏名称
1包含标准库标题的翻译单元不得 在任何标准库标题中声明的#define或#undef名称。
2翻译单位不得在词汇上定义#define或#undef 与关键字,表4中列出的标识符相同,或与 属性标记在10.6中描述。
因此标准禁止您尝试做的事情!
此外,在这种特定情况下它不会起作用,因为您正在用endl
替换某种字符串,导致预处理器生成:std::"\n\r"
导致编译失败。
如果您不想将std::endl
替换为"\r\n"
(BTW:不是"\n\r"
),请手动执行或编写脚本来执行此操作。
答案 1 :(得分:3)
正如已经指出的那样,您不能定义名为endl
的宏。但是,您可以使用名称endl
声明变量(显然位于名称空间std
之外)。你可以拥有
// where the macro is currently define:
extern char const endl[3];
// in a suitable source file including the header with the above declaration:
char const endl[3] = "\n\r";
观察到的行为应该与使用宏相同,只是此声明可以与std::endl
共存。这确实假设您没有使用我认为相当奇怪的L endl
。考虑到这一点,我可以想象你正在使用T(endl)
几乎添加了这个L
,但确实将L
连接到了名称上。如果是这样,您还要添加
extern wchar_t const Lendl[];
带有相应的定义。
如果您想使用endl
,就像使用std::endl
一样,但行为有些不同,我建议您以类似的方式定义它:
template <typename cT, typename Traits>
std::basic_ostream<cT, Traits>& endl(std::basic_ostream<cT, Traits>& out) {
return out << out.widen('\n') << out.widen('\r');
}
当然,将'\n'
字符发送到以文本模式打开的std::ofstream
(或std::wofstream
)时(即不使用std::ios_base::binary
),它会被翻译成[平台特定的]行序列结束。