C ++无法调用std :: endl

时间:2017-09-01 06:23:51

标签: c++ string macros

以更好的方式提出问题:

拥有一个记录器C ++类,其中包含<<运算符重载以接受整数,字符串..

logR <<"Test"<<endl

现在endl被定义为宏

#define endl "\n\r" 

现在在任何.cpp文件中,如果我包含了这个记录器类的头文件,我曾经因使用endl而得到编译错误。

找到一个修复此问题而不是定义宏endl,我重载运算符以接收endl()本身。 感谢有助于解决问题的投入。

2 个答案:

答案 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),它会被翻译成[平台特定的]行序列结束。