tags:

views:

450

answers:

5

Guys would it be difficult to write coutn which would basically place newline symbol at the end of the input. While working with console (that's all I can do at the moment) I'm finding very tedious to write '\n' every time I want the line to be a new line.
Or maybe it is already implemented?

+1  A: 

The way that streams work is that they add one thing and then return itself.

so are you sure you'd want to do what you're asking?

For example:

s << "a" << "b";

Would put:

a
b

Surely you can find a way with some kind of wrapper but the extra overhead incurred and the diminished code readability I don't think is worth it. Most coders are familiar with standard C++. Most coders are not familiar with your coutn and how it works.

Brian R. Bondy
@Bondy -1 No you are WRONG. You shoud use \n instead of endl. In most cases anyway.
There is nothing we can do
std::endl and '\n' are two different things. std::endl also flushes the stream which isn't always wanted.
Yacoby
That's terrible advice. `std::endl` provokes a flush to the output (equivalent to `std::cout.flush()`), which means you lose the benefit of buffering. You only use `std::endl` when you want "instant" feedback, the rest of the time you use `\n` because you only want a newline character.
Matthieu M.
Correct. On some machines an end of line is \r\n. On some machines it's just \n. However, std::endl does the right thing every time.
Pace
I find that flushing the stream 'is' what I usually want, especially in the case of cout.
Salgar
@Knowing me knowing you and @Yacoby: Using a plain "\n" can cause problems when you are in the Windows environment and are using Unicode, in which case the \n will not get handled perfectly -- you'll often be in cases where you'll need to use "\r\n" instead. Using `std::endl` ensures that you are always using the correct newline character for the given situation. Yes, using `endl` incurs the overhead of flushing the buffer, but for most console applications the bottleneck isn't ever going to be console I/O buffer flushing.
Billy ONeal
NO! `cout << '\n'` and `cout << endl` are very different. See http://stackoverflow.com/questions/2245196/c-urban-myths/2245622#2245622
Didier Trosset
@Mathieu: output is usually line-buffered anyway.
Bastien Léonard
@Didier Trosset: They're not the same, yes. However, what makes them different is precisely why you *should* use `std::endl`.
Billy ONeal
Guys no one is claiming they are the same. I removed the bit about using std::endl, I just thought endl was what he really wanted to use. It sounds to me like he wanted to use a newline symbol which would flush the stream.
Brian R. Bondy
It's not necessary to introduce a newline character after each insertion. Think RAII (or look up my answer). I didn't thought about the obnoxious `\r` issue though gah!
Matthieu M.
@Bastien: For an application writing large files to disk, I have seen a speedup by a factor of 5-10 when `std::endl` was replaced by `'\n'`.
sbi
@Billy: So, what you're saying is that VC++ is broken? `'\n'` is the C++ term for end-of-line in streams not opened in binary format, just as a constant integral zero-valued expression is a C++ term for null pointer constant.
David Thornley
I absolutely disagree that you *should* use `endl`. You *can* use `endl` if you want to, and if you understand the resulting performance penalty.
Didier Trosset
I absolutely disagree that you should use `endl` because of Windows `\r\n` line terminations. Changing the `\n` into `\r\n` is done at a lower level than the injection operators. This conversion (from `\r\n` to `\n` on input, and from `\n` to `\r\n` on output streams) is disabled on Windows when you open the stream using the `std::ios_base::openmode` flag `binary` (that is equivalent to C mode "b" of `fopen()`).
Didier Trosset
@ Didier: You might want to note that we are talking about cout here - standard output, which is by default the terminal. Which is line-buffered.
DevSolar
@DevSolar: standard output is not necessarily the terminal. On Unix and Unix-like systems, it's also the input into a pipe to go to the next program, and it's often redirected.
David Thornley
@ David Thornley: From the C standard: "the standard input and standard output streams are fully buffered if and only if the stream can be determined not to refer to an interactive device." So even if you pipe your standard output, it's up to the environment / shell implementation if the pipe / redirection can be *determined* by the C library.
DevSolar
+2  A: 

Roughly:

struct StreamFilterN
{
   ostream & os;
   StreamFilterN(ostream & os_) : os(os_) {}

    template <typename T>
    StreamFilterN & operator<<(T const & x) { os << x << "\n"; return *this; }
}


StreamFilterN coutn(cout);
coutn << "Hello world";
coutn << "Yeah, like.";

(I'm not sure if this works perfectly, but it should get you started)

peterchen
We've had the same idea... though there is no `'\n'` anywhere in your answer ?
Matthieu M.
+1 Even though there needs to be a os << '\n'; before returning the stream again, it's the solution I find the nicest.
Christian
I'd add `explicit` to the constructor
sellibitze
@Christian: `coutn << "result: " << r` leads to 2 lines of output. You may find it nice, but it doesn't fulfill the requirements.
Matthieu M.
@Matthieu M.: When posting the comment, I didn't know the op wanted the newline to be added only after the last <<. Given the new requirement, you're obviously right ;)
Christian
@Matthieu: Egads! Thanks for pointing out.
peterchen
@Christian: Argh sorry, only saw the new requirements... that's the problem with editing the question/answer: you never know which version the comment are referring to :)
Matthieu M.
+4  A: 

Well, the first obvious thing would be to implement some kind of wrapper around it:

class Print
{
public:
  explicit Print(std::ostream& stream = std::cout): mStream(stream) {}
  ~Print() { mStream << '\n'; }

  template <class T>
  Print& operator<<(T const& t) { mStream << t; return *this; }

private:
  std::ostream& mStream;
};

Usage is like such:

int main(int argc, char* argv[])
{
  Object object;
  Print() << "My new object value: " << object;

  std::ofstream file("file.log");
  Print(file) << "My new object value: " << object;
}

Easy, Peasy.

Matthieu M.
Yes. Let's replace the tedious two extra characters with a header file, two functions, a template function, a class, and then require more than that two characters whenever anyone wants to use it :\
Billy ONeal
Yep, why not?Anyhow it needs:#define coutn Print()to be complete.
Shiroko
Don't forget the `#define coutn Print()`
Gabe
@Billy as I've said in my latest comment two you it's not two chars but four. Becoming more and more tedious don't you think so?
There is nothing we can do
I don't like the `#define`. The purpose of this object is to be able to choose which stream you output to. As for the name, well if it really matters you can always replace `Print` by `coutn`... but it does not change the design.
Matthieu M.
@Billy: The real point, as has been mentioned, is to have this method handles the different platforms as well. `#ifdef` directives should be used to detect the Linux / Windows / Mac world and replace `\n` with the appropriate newline character(s). This is when your `\n` sprinkled everywhere are tedious to replace and where a function shines.
Matthieu M.
For any stream opened in text mode (i.e., not binary mode), writing `\n` to the stream causes the platform-specific line ending to be written to the stream, even if the platform-specific line ending is not `\n`.
James McNellis
@Matthieu M.: Why do I have to invent a way to handle the correct newlines when iostreams already provides a perfectly good mechanism for doing so?
Billy ONeal
@James McNellis: The wide character specializations often don't handle that correctly.
Billy ONeal
@Knowing me knowing you: I don't see how it became 4 characters. Nobody cares how many characters are there. The only thing anyone cares about is how readable your code is. Adding those characters goes a long way toward helping the next person reading your code.
Billy ONeal
@Billy first of all in standard way you have to type at least four extra chars (1' 2' 3\ 4n) or SIX (( 1< 2< 3' 4' 5\ 6n). Second thing is that coutn is much more understandable and expressive to cout because you immediately know looking at coutn that this line ends with \n. More readable.
There is nothing we can do
@Billy: Hmmmmmmm. Even if you use a wide string literal? (`L"\n"`)
James McNellis
@James: Yes, even if you use a wide string literal. (It won't even compile otherwise)
Billy ONeal
@Billy: Which platform and how were the streams constructed?
Roger Pate
+11  A: 

To circumvent the multiple injections on a single line, you could use a temporary object. This temporary object would add the '\n' in its destructor.

struct coutn {
    coutn(): os(cout) {}
    ~coutn() { os << '\n'; }
    template <typename T>
        coutn & operator<<(T const & x) { os << x; return *this; }
private:
    ostream &os;
};

coutn() << "Hello " << "World" << "!";

In the end, I'm wondering if this coutn is actually better?

Didier Trosset
+1: Sanity of the desire notwithstanding, this is the best way to fulfill it.
Derrick Turk
+1 This was the same idea that I had (except you posted 20 second before me)
Yacoby
Hmm... seems odd to replace two characters "\n" with three "n()"... (+1 to the answer, the question is inherently asking for something stupid)
Billy ONeal
@Billy ONeal what's stupid in wanting to type less than more with the same effect? Really looking forward to your answer.
There is nothing we can do
@Knowing me knowing you: Because code readability is more important than code length. And this solution has you typing *more*, not less.
Billy ONeal
@Billy ONeal what unreadable about coutn? In my opinion it's more readable than cout because you have to check the end of the line to know what it really does and with coutn you do not have to do it. It is just more readable.
There is nothing we can do
@Knowing: .... stay the hell away from my codebase, and I'll stay the hell away from yours.
Billy ONeal
@ Knowing me knowing you - The "unreadable" part of `coutn` is that it looks *almost* like the standard `cout` but isn't, and no-one except you would be using it.
DevSolar
Probably adding a macro could make a bit more better in terms of typing... If you name the class CoutN and use a macro like..`#define coutn CountN()` might actually help you use it like`coutn<<"what's the meaning of life?";``coutn<<"Ans: "<<42;`
Vite Falcon
@Billy, sometimes 2 characters is more than 2 characters. If the last thing you output is a variable, then you have to add `<< '\n'`, for a total of 7 new characters. (More if you want `<< std::endl` instead).
Ken Bloom
@Ken: Note that if you want `<< std::endl` instead of a raw new line, you can't use `coutn` as it is implemented here anyhow. You have to do `coutn() << blah; cout.flush();` which is a net loss no matter how you count things.
Dennis Zickefoose
@Dennis. but you could *very* easily modify coutn, and I assume nobody here needs me to tell them that modification was implied.
Ken Bloom
+1  A: 

Come one people. You must admit that C++'s newlines are too verbose. Look at C#, D, Java, Python, Ruby, should I go on? I don't think you should implement a coutn. I think you'd be better off following D's example with write, writeln, writef, and writefln variadic template functions.

Anyway here is how to do it without macros and with out needing to explicitly create temporaries.

class coutn_t
{
private:
   class newliner
   {
   public:
      explicit newliner(std::ostream & out=std::cout) : m_out(out) { }

      template<typename T>
      newliner& operator<<( const T& t)
      {
         m_out << t;
         return *this;
      }
      ~newliner() { m_out << std::endl; }
   private:
      std::ostream & m_out;
   };
public:
   // NOTE: these return by value.  Only one newliner will be
   // destructed however as RVO will eliminate the copy.

   newliner operator()( std::ostream& out )
   { return newliner(out); }

   template< typename T >
   newliner operator<<( const T& t )
   {
      std::cout << t;
      return newliner(std::cout);
   }
};

coutn_t coutn;

coutn << "Hello World!";

coutn << "Hello " << "World" << '!';

std::ofstream file("ouput.txt");
coutn(file) << "Hello World" << " via file";

The complete solution will have to add more overloads for operator<< to handle stream manipulators (std::hex etc). The functions returning newliners must always be inline to allow RVO.

caspin