简体   繁体   中英

C++ unable to call std::endl

Framed the question better manner:

Have a logger C++ class which has the << operator overloaded to accept ints, strings..

logR <<"Test"<<endl

Now the endl had been defined as macro

#define endl "\n\r" 

Now in any .cpp file if i included this logger class's header file i used to get compilation error for using endl.

Found a fix for this instead of defining macro endl, I overloaded operator to receive the endl() itself. Thanks for the inputs it helped in solving the issue.

From the standard N4687 :

20.5.4.3.2 Macro names

1 A translation unit that includes a standard library header shall not #define or #undef names declared in any standard library header .

2 A translation unit shall not #define or #undef names lexically identical to keywords, to the identifiers listed in Table 4, or to the attribute-tokens described in 10.6.

So what you are trying to do is prohibited by the standard!

Additionally in this specific case it won't work because you are substituting endl for a string of some sort, causing the preprocessor to generate this: std::"\\n\\r" which causes the compilation to fail.


If you wan't to replace std::endl by "\\r\\n" (BTW: not "\\n\\r" ) then do it by hand or write a script to do it.

As was pointed out already, you are not allowed to define a macro with the name endl . However, you are allowed to declare a varaiable with the name endl (outside namespace std obviously). So you could have

// 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";

The observed behavior should be the same as using the macro except that this declaration can coexist with std::endl . That does assume that you don''t use L endl with which I'd consider rather odd. Thinking of it, I can imagine you are using T(endl) which nearly adds this L but accually concatenates L to the name. If so, you'd just also add

extern wchar_t const Lendl[];

with a corresponding definition.

If you want to use your endl just like std::endl is used but with some different behavior, I'd recommend defining it in a similar way, too:

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');
}

Of course, when sending a '\\n' character to a std::ofstream (or an std::wofstream ) opened in text mode (ie, without using std::ios_base::binary ) it gets translated into the [platform specific] end of line sequence.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM