walrus137's blog

By walrus137, history, 7 months ago, In English

cin >> x, just makes so much sense now.

Analogy

This thing is just syntax sugar which c++ provides.

Like when we want to write: x = x + a We can instead write: x += a

Which is exactly the same thing.

edit: these are not exactly the same things, and thus not even a good analogy, but fine to get the point.


What is operator>>

Similarly we have operator>>, which is used to take in input from an input stream. And depending on the type for the x variable two things can happen.

If x is a built-in type then cin.operator>>(x): is called, which is a member function of the cin class, and has been defined for a built-in type.

But if x is not a built-in type, then we have to manually provide how the input is going to be interpreted.

By defining a function with the below signature:

   std::istream& operator>>(std::istream& is, my_type& x){};

This is a function which takes in a reference to an input stream and a reference to our variable x and defines how x is going to be filled.

and when we do: cin >> x;

For our custom type x, the above function is called: operator>>(cin,x);

And not: cin.operator>>(x);

Since there is no member function of cin defined for type of x.

That is crazy. And just makes so much sense now, >> and << are just syntactical sugar over the actual function calls.


same for operator<<

Again for outputting two things could happen depending on the type of x.

If x is a built-int type then: ostream.operator<<(x);

If x is not a built-in type then: operator<<(ostream,x);


why cin >> x >> y >> z; works?

Now the amazing thing about why we can do this: cin >> x >> y >> z; ( symmetrically the same applies to operator<< for outputting)

This is because operator>> returns an input stream and if we remove the syntactical sugar with the actual function calls being made in order, we have something like this:

cin >> x >> y >> z;

cin.operator>>(x) >> y >> z;

cin.operator>>(x).operator>>(y) >> z;

cin.operator>>(x).operator>>(y).operator>>(z);

And this makes sense because cin.operator>>(x) returns an input stream and then we get the .operator>>() member function for that returned input stream and call that with y and so on with z.

That is just so cool and everything seems to be demystified now. That is crazy. really.

PS: This is my first blog, please point out the mistakes I made.

  • Vote: I like it
  • +46
  • Vote: I do not like it

»
7 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

Auto comment: topic has been updated by walrus137 (previous revision, new revision, compare).

»
7 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

Auto comment: topic has been updated by walrus137 (previous revision, new revision, compare).

»
7 months ago, hide # |
 
Vote: I like it +19 Vote: I do not like it

Not std::istream operator>>(std::istream& is, my_type& x){}; but std::istream& operator>>(std::istream& is, my_type& x){};.

»
7 months ago, hide # |
 
Vote: I like it +12 Vote: I do not like it

In fact, every operator of class type in C++ works the same. For example, string s="Hello",t="World"; s+=t; is equivalent to string s="Hello",t="World"; s.operator += (t);

  • »
    »
    7 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    Thanks for that. This just seems amazing, that these things can be this simple and intuitive under the hood.

»
7 months ago, hide # |
 
Vote: I like it +23 Vote: I do not like it

x += a is not the same as x = x + a.

The following code fails in custom invocation with TIME_LIMIT_EXCEEDED:

#include <bits/stdc++.h>
using namespace std;
int main(){
    int i;
    
    string s;
    for(i=0; i<1000000; i++){
        s = s + ".";
    }
}

The following doesn't:

#include <bits/stdc++.h>
using namespace std;
int main(){
    int i;
    
    string s;
    for(i=0; i<1000000; i++){
        s += ".";
    }
}
  • »
    »
    7 months ago, hide # ^ |
     
    Vote: I like it +8 Vote: I do not like it

    That makes sense, Thanks for that.

    When I wrote x += a, I had integers in mind, but still even with integers what I wrote is wrong.

    I guess because when we do x = x + a, we get a new variable whose value is x + a using operator = on it invokes the copy constructor and creates a copy of this already existing variable x + a and copies it to x, so we had two copies of the same thing, bad

    But with x += a we add a to x itself and we don't create a copy.

    • »
      »
      »
      7 months ago, hide # ^ |
      Rev. 2  
      Vote: I like it +1 Vote: I do not like it

      Note that = in x = x + a calls the move assignment with method signature string& operator=(string&& str) because x + a is an r-value. So, that does not make an additional copy. x will free its memory and take the memory of x + a. Only problematic part is allocation of temporary strings due to the + operation. x += a just calls x.append(a) internally.

      Edit: Helpful blog though. I don't know why it was downvoted.

      • »
        »
        »
        »
        7 months ago, hide # ^ |
         
        Vote: I like it 0 Vote: I do not like it

        Oh, that is true, makes sense, So the in efficiency is due to the fact we are creating a temporary r-value string.

        Thanks for pointing that out. :)

»
7 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

absolutely elite font choice

»
7 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

Auto comment: topic has been updated by walrus137 (previous revision, new revision, compare).

»
7 months ago, hide # |
Rev. 3  
Vote: I like it +7 Vote: I do not like it

#include<iostream> is also just styntactical sugar !!!

Spoiler
»
7 months ago, hide # |
 
Vote: I like it +9 Vote: I do not like it

why do you call this syntactical sugar? you're just using standard operators, so there is no sugar. or do i misunderstand the meaning of this concept?

  • »
    »
    7 months ago, hide # ^ |
     
    Vote: I like it +4 Vote: I do not like it

    If you're familiar at all with the greatest programming language, the simplest example of syntactic sugar is the single apostrophe: 'x is syntactic sugar for (quote x). Because writing (quote sym) all the time when we want an unevaluated symbol is annoying, this syntax was introduced, even though it's unnecessary and not strictly fundamental.

    I'm not a C++ expert so I don't know how fundamental operator overloading is (is the AST generated by x.operator+(y) the same as the AST generated by x+y?) but if C++ operator overloading is just an equivalent alternative to writing operatorXYZ everywhere, and there is nothing inherently different about it aside from syntax, it is just syntactic sugar.

  • »
    »
    7 months ago, hide # ^ |
    Rev. 2  
    Vote: I like it 0 Vote: I do not like it

    An operator is a shorthand for calling a function/method, except for primitive types such as int, float, etc. Consider what would happen if we did not have operator overloading. a + b - c will look like sub(add(a, b), c). We are used to infix notation so the former is easier to read.

    Quoting Wikipedia:

    In computer science, syntactic sugar is syntax within a programming language that is designed to make things easier to read or to express. It makes the language "sweeter" for human use: things can be expressed more clearly, more concisely, or in an alternative style that some may prefer. Syntactic sugar is usually a shorthand for a common operation that could also be expressed in an alternate, more verbose, form: The programmer has a choice of whether to use the shorter form or the longer form, but will usually use the shorter form since it is shorter and easier to type and read.

    Although, in the case of C++, syntactic diabetes is the more appropriate term. :p

    If C++ was a, new, well-designed languages then the following would work:

      vector<string> shards{"Hello, "s, "world!"s};
      auto sentence = ranges::fold_left(shards, ""s, string::operator+=);
    

    Instead, we have to do this:

      vector<string> shards{"Hello, "s, "world!"s};
      auto sentence = ranges::fold_left(shards, ""s, [](auto&& acc, auto&& x) { return acc += x; });
    

    P.S. Most C++ LSPs support go to definition for operators, so you can do Ctrl + Left click on an operator to go to the function/method that is being called.

»
7 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

This is operator overloading and it can be done with almost any operator