11

When I compile this program:

#include<iostream>

using namespace std; 

std::cout<<"before main"<<endl;

int main()  
{

}

...I see this error from the compiler:

error: expected constructor, destructor, or type conversion before '<<' token

Please help me understand what this means and what's wrong with my program?

Cœur
  • 37,241
  • 25
  • 195
  • 267
abcd
  • 111
  • 1
  • 4
  • 10
    The question is why most c++ compiler give such crappy error messages. – log0 May 04 '11 at 09:11
  • Hopefully a smart compiler can generate better errors. – Eric Z May 04 '11 at 09:19
  • 1
    Well, it's not easy to give a meaningful message in this case. Even clang says: "error: no type named 'cout' in namespace 'std'" and "error: expected unqualified-id" for the `operator<<`. – Tamás Szelei May 04 '11 at 09:51
  • @Ugo: It's easy for humans to read and see the error because we are seeing more context than the compiler is seeing at the point of the error. The compiler has only seen what is before the point of the error (and maybee a token or two after the error as it tries to determine the error). So given this and an understanding of the C++ grammar the error becomes a lot more obvious. The compiler saw std::cout and is now looking for either 'constructor, destructor, or type conversion' as these are the only next tokens that would make a valid declaration or statement (and thus a valid program). – Martin York May 04 '11 at 14:54
  • 1
    @Martin I agree with you and I am aware of the issues one can encounter while writing a compiler (really). But sometimes it just make me sad. For example we had to wait gcc4.6 for "clearer diagnostics for missing semicolons after |class|, |struct|, and |union| definitions"... structs appeared in C almost 40 years ago :'(. – log0 May 04 '11 at 16:03

5 Answers5

14

You're seeing that error because your

std::cout<<"before main"<<endl;

statement needs to be within the scope of your main() function (or some other function) in order for this program to be valid:

int main()
{
   std::cout<<"before main"<<endl;
}

Unrelated to your specific question, one extra point: as you are using namespace std, the explicit std:: on std::cout is redundant.

razlebe
  • 7,134
  • 6
  • 42
  • 57
  • 6
    Returning an integer from main is optional. The standard states that an implicit `return 0;` is added before the closing brace in the main function. This is only valid for `main`, all other functions must return if their signatures specifies a return type. – David Rodríguez - dribeas May 04 '11 at 09:19
  • but if there is a global object before main, inside that global object's constructor cout wokrs..i can't understand why it is not working before main – abcd May 04 '11 at 09:19
  • 1
    @David Rodriguez - Agreed, that's why I said "should be returning" rather than "must return". Even though it's optional, it's still good practice. – razlebe May 04 '11 at 09:24
  • @abcd - A constructor is a function, so your statement is valid there. What you can't do is plop a statement in the middle of a source file, all on it's own - it's meaningless, and will never be executed. See the answer by @Nawaz for another example of where a statement is valid, other than within a function. – razlebe May 04 '11 at 09:27
  • @David Rodriguez - Updated my answer for clarity - thanks for the feedback. :) – razlebe May 04 '11 at 09:31
  • 1
    @jhasse For clarity, I guess. The standard specifies (3.6.1/5) that not explicitly returning from main is the equivalent of `return 0`, but in my experience it never hurts to be explicit about it. It's not a problem with this tiny program here. – razlebe May 04 '11 at 09:57
  • @razlebe: I'd say it's commonly good practice not to write code that has no effect – jalf May 04 '11 at 13:02
  • @jalf In this specific case I agree, it's pointless - but it's a good habit to be in for those cases when there are several return points, a multitude of return values, etc. – razlebe May 04 '11 at 13:08
  • @razlebe: no, I still disagree. If I end up in the situation where "I need to return 0 now, rather than continuing execution", then I put a return statement, because nothing else will work. I don't need "a habit" for that, any more than I need a "habit" of using the `+` operator when I want to add two values together. It's the only sane way to achieve the stated goal, so obviously, it is what I'm going to do, habit or no habit – jalf May 04 '11 at 13:13
  • @jalf Perception of clarity is a highly subjective topic. I respect your opinion, thanks for the feedback. – razlebe May 04 '11 at 13:21
7

Statements cannot be executed outside functions.

However, if you make that expression which is used to initialize a global variable, then that will be okay in the sense that compiler will not give any error or warning.

For example, the following code will print what you want to print:

#include <iostream>

std::ostream &gout = std::cout<<"before main"<< std::endl;

int main() { }

Output:

before main

Online demo : http://www.ideone.com/Hz4qu


Here I do almost the same thing as done in this topic:

Is main() really start of a C++ program?

Community
  • 1
  • 1
Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • 3
    In fact it's trivial to make a utility to generalize it: http://www.ideone.com/Iotcc – GManNickG May 04 '11 at 09:46
  • 1
    This is problemantic in that it is prone to the initialization order fiasco. There is no guarantee that the initialization of `gout` happens *after* the initialization of `std::cout` so you might end up calling `operator<<` on an uninitialized `cout` -> undefined behavior – David Rodríguez - dribeas May 04 '11 at 11:10
  • @David: You mean, if I write `int global_i = 100; int global_j = 2 * global_i`, then it is not guaranteed that `global_i` will be initialized before `global_j`? – Nawaz May 04 '11 at 12:05
  • @Nawaz: If both are in the same translation unit, the order is guaranteed, if they are defined in different translation units, the order is undefined. I.e. `/* a.cpp */ int a = 10; int b = 2*a; /* b.cpp */ extern int a; int c = 2*a;` when `main` starts, `a==10` and `b==20`, but `c` might be either `0` or `20` (`0` as `a` being an `int` will be initialized to `0` before any other initialization occurs) – David Rodríguez - dribeas May 04 '11 at 13:14
  • @Nawaz @David: I clarified this on my blog, just now, because it's interesting. http://www.gmannickg.com/?p=197 – GManNickG May 05 '11 at 00:57
  • @Nawaz: How this works std::ostream &gout = std::cout<<"before main"<< std::endl ? – Destructor Jul 06 '15 at 13:24
  • @PravasiMeet: `gout` is a namespace level variable, which MUST be initialized before `main()` begins. But in order to initialize it, the right hand side must be executed (as a result of which the string *"before main"* gets printed on `stdout`) and the return value is stored as reference in `gout`. Makes sense? – Nawaz Jul 06 '15 at 14:07
6

you cannot write

std::cout<<"before main"<<endl;

outside a function.

-- edit --
The single entry point of a c++ program is the main function. The only thing that may occur before the execution of the main function is the initialization of static/global variables.

static int i = print_before_main_and_return_an_int();
log0
  • 10,489
  • 4
  • 28
  • 62
  • yeah..that is evident from the output of my program...i want to know the reason... – abcd May 04 '11 at 09:18
  • This is prone to order of initialization issues. There is no guarantee that `cout` will be initialized before `i` is. – David Rodríguez - dribeas May 04 '11 at 11:53
  • @abcd: hmm? You asked what was wrong with your program. What is wrong is that you put the `std::cout` line before the main function. Are you now asking *why* it is an error to do that? – jalf May 04 '11 at 13:06
3

You have to define the line inside a function.

std::cout<<"before main"<<endl;
Eric Z
  • 14,327
  • 7
  • 45
  • 69
0

The above answers are correct but just to add. If you already have:

#include<iostream>
using namespace std;

You dont a have to type:

std::cout<<"before main"<<endl;

You can just type:

cout<<"before main"<<endl;

Because you already declared that your using namespace std; can save you a little typing. Cheers!

Mekanic
  • 137
  • 2
  • 10