2

Recently, I was curious as to what would happen if I declared a std::ifstream called cin, then tried to read input with it. I thought that this would result in a compilation error, because the compiler wouldn't be able to differentiate whether to use the std::istream or the std::ifstream for the input operation. Here's the code I wrote to test this:

#include <iostream>
#include <fstream>
#include <cmath>
#include <algorithm>
#include <vector>

using namespace std;

int main()
{
    ifstream cin("math_testprogram.in");

    int N;
    cin >> N; // I expect this line to result in some sort of
              // "reference to cin is ambiguous" error

    cout << N << "\n";

    return 0;
}

The current code (on my compiler, at least) tries to read N from the file instead of standard input. If I change the cin >> N line to std::cin >> N, however, then the program starts trying to read N from standard input (as expected).

My question is, why doesn't the compiler give an error in this case (the compiler I compiled this program with is GCC 7.5.0)? Is there some other misconception that I'm making here?

Telescope
  • 2,068
  • 1
  • 5
  • 22
  • 3
    Local variables always take precedence over globals, right? So the code is perfectly legal. I guess it's a little surprising that `-Wshadow` doesn't warn about it, though. – Nate Eldredge Jan 25 '21 at 00:33
  • I am pretty sure `-Wshadow` would warn about that. "Turn you compiler warnings on" is probably the best and least followed advice. – spectras Jan 25 '21 at 00:40
  • @spectras gcc doesn't; clang does: https://godbolt.org/z/1K7hMe – bolov Jan 25 '21 at 00:51
  • Slightly related: [Why is "using namespace std;" considered bad practice?](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice) – Some programmer dude Jan 25 '21 at 00:54

1 Answers1

3

The same identifier can be used for different variables:

  • in different namespaces, and
  • inside a code block, with the inner scope overruling the outer scope.

In your code you do both of these things. The global object called std::cin and the local object of main function called cin can coexist with no problem.

A name declared in a code block hides the same name from a more outer scope. After you have declared your own cin, then you would need to write std::cin to get that one.

M.M
  • 138,810
  • 21
  • 208
  • 365