tags:

views:

465

answers:

6

So I was doing some simple C++ exercises and I noticed an interesting feat. Boiled down to bare metal one could try out compiling the following code:

class nice
{
  public:
    nice() {}
};

int main()
{
  nice n;
  return 0;
};

The result is a compilation error that goes something like this:

<file>.cpp: In function ‘int main()’:
<file>.cpp:11: error: expected `;' before ‘n’
<file>.cpp:11: warning: statement is a reference, not call, to function ‘nice’
<file>.cpp:11: warning: statement has no effect

And this was using regular g++ on Max OS X, some of my friends have tried in on Ubuntu as well, yielding the same result.

The feat seems to lie in the word "nice", because refactoring it allows us to compile. Now, I can't find the "nice" in the keyword listings for C++ or C, so I was wondering if anyone here had an idea?

Also, putting

class nice n;

instead of

nice n;

fixes the problem.

P.S. I'm a relative C++ newbie, and come from the ActionScript/.NET/Java/Python world.

Update:

Right, my bad, I also had an

#include <iostream>

at the top, which seems to be the root of the problem, because without it everything works just fine.

+2  A: 

It works fine for me. Did you try the exact code you posted?

Matthew Flaschen
Right, no, I had a #include <iostream> at the top :) that's probably it.
oleks
+16  A: 

Maybe the problem is somehow caused by function nice in libc. It is similar to trying to name your class printf.

Messa
+4  A: 

using namespace std, by any chance?

Edit:

The standard says that standard headers define all their symbols in namespace std (see 17.4.1.2.4). A footnote, however, also says that the <.h> variants dump their names into the global namespace - but of course no one should be using these ;)

Autopulated
The footnote refers to the `<stdio.h>` variants; the ones inherited from C. There is no .h variant of `<iostream>` in ISO C++. An implementation may provide one, though, as the headername <iostream.h> is not reserved by ISO C++
MSalters
@MSalters yes, exactly: <iostream> isn't a c header, hence it does not put *any* symbols into the global namespace.
Autopulated
+3  A: 

Try this version:

#include <iostream>

namespace test
{
    class nice
    {
    public:
        nice() {}
    };
};

using namespace std;

int main()
{
    test::nice n;
    cout << "well I think this works." << endl;
    return 0;
}

In this case I've defined my own namespace test. Doing so, I can use whatever class names I like, including functions already defined like printf. The only things I can't re-use are reserved words like int or namespace.

Note: if you say:

using namespace test;

As well and refer to nice alone, you'll get this error:

nice.cpp: In function ‘int main()’:
nice.cpp:18: error: reference to ‘nice’ is ambiguous
/usr/include/unistd.h:593: error: candidates are: int nice(int)
nice.cpp:7: error:                 class test::nice

Which I think explains nicely what's going on - nice now exists in two namespaces and the compiler can't work out which one you mean.

Ninefingers
In case anyone is curious (as I was), here's some information about the function std::nice() http://www.gnu.org/software/libc/manual/html_node/Traditional-Scheduling-Functions.html#Traditional-Scheduling-Functions (scroll down to the bottom)
MatrixFrog
Yeah, niceness is a value used by the Linux kernel for scheduling purposes. It's just occurred to me that's what this is for...
Ninefingers
nice() is *not* in std, it is global.
Duck
+2  A: 

It is a namespace problem but not with namespace std. The header <iostream> is pulling in <unistd.h>

If you try

class nice
{
  public:
      nice() {};
};

int main(int argc, char *argv[])
{
    nice n;

    return 0;
}

there is no problem.

Simply add

#include <unistd.h>

and you will get the "expected ‘;’ before ‘n’" error. Namespace std does not enter the picture.

So the solution is the same as before - put class nice in its own namespace and it will not clash with the global ::nice().

Duck
A: 
extern "C"
{
#include <unistd.h>
}
mateuszb