3

Coding away this evening (I realise it's Valentine's Day) and came across something strange...

I have the following line:

std:;cout << freqs[summations[i]] / 1000 * 10 << std::endl;

This compiles. However, if I do this, it will not compile.

std;;cout << freqs[summations[i]] / 1000 * 10 << std::endl;

I don't have any strict properties on in my compile line. However, I wouldn't have thought GCC would allow this to be compiled and output. Why is this?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Phorce
  • 4,424
  • 13
  • 57
  • 107
  • goto's in most firms are forbidden so people haven't seen single label in entire career. – PiotrNycz Feb 14 '14 at 23:43
  • @PiotrNycz How do you mean `goto` have I used such a statement..? – Phorce Feb 14 '14 at 23:43
  • Most people have seen a `default:` label, I expect, inside a `switch`, of course. – Jonathan Leffler Feb 14 '14 at 23:43
  • @Cornstalks damn you ;) thank you!! This can be closed! – Phorce Feb 14 '14 at 23:46
  • @user1326876: I knew I had seen this before, but it took forever for me to find the original question, so I certainly don't blame you for asking it again (since it was so dang hard to find)! – Cornstalks Feb 14 '14 at 23:47
  • @JonathanLeffler `default:` is not a real label in a sense that ypu can't `goto default;` – PiotrNycz Feb 14 '14 at 23:54
  • @PiotrNycz: true enough; you can't goto a case label, either. ISO/IEC 14882:2012 Section 6.1 **Labels** states _Case labels and `default` labels shall occur only in switch statements._ and 6.6.4 **The `goto` statement** says _The goto statement unconditionally transfers control to the statement labeled by the identifier._ and, of course, `default` is a keyword, not an identifier. – Jonathan Leffler Feb 15 '14 at 00:03

3 Answers3

6

std:; is getting parsed as a label followed by an empty statement.

Jim Lewis
  • 43,505
  • 7
  • 82
  • 96
5

The first line provides a label std: followed by a null statement -- the semicolon.

The rest uses cout << ... and means you must have a using namespace std; or using std::cout; or something similar in effect.

The second uses an identifier std that isn't defined.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • I think I understand where you're coming from. However, I do not not have `using namespace std;` or `using namespace std::cout` anywhere in my code – Phorce Feb 14 '14 at 23:30
  • Well, something is there that allows `std::cout` without the prefix `std::` because you said it compiles. The obvious thing to do is remove the `std::` from `std::endl` on the same line and see whether that compiles. It's not 100% definitive if it does not because there could be a `using` declaration hidden somewhere. – Jonathan Leffler Feb 14 '14 at 23:34
  • Not hidden ;-) I've always been told not to include `using namespace std;` if using just `std::cout` mhm. This would therefore break the rules? – Phorce Feb 14 '14 at 23:38
  • Did you try removing `std::` from `std::endl`? I've compiled `void p(int i) { cout << i << std::endl; }` with `#include ` and it fails; add either `using namespace std;` or `using std::cout;` and it does compile. You may have to preprocess the file (`g++ -E`) to find the `using` declaration or `using` directive. Because of the compilation options I use, I had to add a `goto std;` to get the code to compile with the `std:;cout ...` notation. – Jonathan Leffler Feb 14 '14 at 23:41
  • And, just for the record, this was GCC 4.8.2 on an Ubuntu 12.04 derivative and the command line options were: `g++ -g -O3 -std=c++11 -Wall -Wextra -Werror -c x.cpp`. – Jonathan Leffler Feb 14 '14 at 23:50
0

std:; is a label. The other part is using argument dependent name lookup to resolve the namespace.

Since you said you didn't use using namespace in your code. My guess is that it works because you are using std::endl in the end (if you removed std from the endl it won't compile). which is using argument dependent name lookup. Which is part of the standard:

ADL occurs only if the normal lookup of an unqualified name fails to find a matching class member function. In this case, other namespaces not considered during normal lookup may be searched where the set of namespaces to be searched depends on the types of the function arguments. Specifically, the set of declarations discovered during the ADL lookup process, and considered for resolution of the function name, is the union of the declarations found by normal lookup with the declarations found by looking in the set of namespaces associated with the types of the function arguments.

concept3d
  • 2,248
  • 12
  • 21
  • Sounds plausible, but doesn't seem to work. Trying `void p(int i) { cout << i << std::endl; }` with just `#include ` and I get an error which I wouldn't if your hypothesis was accurate. – Jonathan Leffler Feb 14 '14 at 23:37
  • @JonathanLeffler yes, I agree, actually on MSVC2012 it didn't even compile the OP version. On g++ it did but only when I used a label. Which is puzzling me to be honest. – concept3d Feb 14 '14 at 23:49
  • I guess we have to start asking 'which version of `g++` and which compilation options?' I used `g++` 4.8.2 on an Ubuntu 12.04 derivative with options `g++ -g -O3 -std=c++11 -Wall -Wextra -Werror -c x.cpp`. I'm guessing you're using `g++` on Windows, so probably MinGW or Cygwin? – Jonathan Leffler Feb 14 '14 at 23:53