As the title mentioned. The following code shows error :
#include <iostream>
using namespace std;
class link
{
public:
link()
{
num=0;
next=NULL;
}
int num;
link* next;
};
int main() {
link test;
return 0;
}
compile this code with
g++ test.cpp -o test
my g++ versions is
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
And the compiler shows the following error
test.cpp: In function ‘int main()’:
test.cpp:18:10: error: expected ‘;’ before ‘test’
If I comment this 'link test' statement, then everything is ok.
Besides, if I replace 'link' with other name like 'Link', everything is ok too.
In Visual Studio or VC, the code is ok.... So it confused me very much.
To summarize the comments:
GCC includes a function named link. For C compatibility, C++ allows you to define a struct (or class) with the same name as a function, but you have to disambiguate them on use.
I.e. in this case, the fix is class link test;
The use of link inside the definition of class link is an exception, there it always refers to the class itself. This is necessary to be able to write the constructor, as you can't disambiguate the name there. There's no syntax which would allow it.
There is a int link(const char *path1, const char *path2); function in unistd.h, which appears to be included from iostream. Gcc has had some problems with this kind of problem in the past. (I note that 4.7.2 doesn't show this behavior.)
As noted by MSalters, adding a
class link test;
should disambiguate the problem.
Related
While trying to compile some CUDA code using Intel Threading Building Blocks, I discovered what I think is a bug in nvcc. The following minimal example compiles fine using g++ 5.4:
class Sub;
class Other;
namespace internal {
class Base
{
private:
friend class ::Sub;
static void foo(::Sub& b);
static void foo(::Other& c);
};
}
class Sub : private internal::Base
{
public:
using internal::Base::foo;
};
void internal::Base::foo(Sub& b)
{
}
int main(int argc, char *argv[])
{
Sub *b;
b->foo(*b);
// Sub::foo(*b);
return 0;
}
But if I compile it with nvcc 8.0 combined with the same host compiler, using
nvcc -x cu -arch=sm_35 -c minimal.cc
I get the following interesting error:
../minimal.cc: In function ‘int main(int, char**)’:
../minimal.cc:28:21: error: ‘internal::Base’ is an inaccessible base of ‘Sub’
A somewhat more descriptive error is obtained if Base is moved out of the internal namespace and into to global namespace:
../minimal.cc: In function ‘int main(int, char**)’:
../minimal.cc:6:12: error: ‘class Base Base::Base’ is inaccessible
class Base
^
../minimal.cc:32:5: error: within this context
b->foo(*b);
^
../minimal.cc:32:11: error: ‘Base’ is an inaccessible base of ‘Sub’
b->foo(*b);
Clearly, this seem to be due to the somewhat non-standard way of calling the static method using a pointer, and if that row is replaced by the one commented out, it compiles just fine.
Can someone confirm if this is valid C++ and thus a bug in nvcc, or invalid C++ that g++ somehow still happily accepts?
I dug some more into this, and saw that it indeed is a problem with one of the phases of the nvcc compilation. Using --save-temps, and checking out the resulting .cu.cpp.ii file, it turns out that this line
b->foo(*b);
gets substituted by the following
(b->internal::Base::foo(*b));
This does not compile with g++, since then the fact that foo is exported as public in Sub is lost. After all, this tries to explicitly access it from the base class where it is private. Using the other type of invocation (Sub::foo) does not result in any extra code being generated.
I conclude that this is an bug in nvcc. It is interesting that this substitution does not happen if the second overloaded void foo(::Other &c) is not declared in Base.
I have a simple program containing the following code:
namespace nam
{
struct S{};
void f(S *){}
}
void f(nam::S *){}
int main()
{
nam::f(nullptr);
nam::S s;
f(&s);
return 0;
}
I expect that this will compile fine because I am calling f the second time without specifying namespace nam. However, upon compiling the code, I get this error:
$ g++ main.cpp -std=c++11 -Wall -Wextra
main.cpp: In function ‘int main()’:
main.cpp:14:9: error: call of overloaded ‘f(nam::S*)’ is ambiguous
f(&s);
^
main.cpp:7:6: note: candidate: void f(nam::S*)
void f(nam::S *){}
^
main.cpp:4:10: note: candidate: void nam::f(nam::S*)
void f(S *){}
Compiler and version:
$ gcc --version
gcc (Debian 5.3.1-14) 5.3.1 20160409
After trying this with different compilers, similar errors are returned. This seems to be a defined part of C++. I can't find anywhere on the internet where it says that calling a function with a struct in namespace nam as a parameter effectively implies using namespace nam; and requires ::f to remove ambiguity. I have 2 questions about this:
Where is this defined in the C++ standard?
Is there a good reason for this behavior?
Personally I like to avoid using namespace x; and similar. I want the compiler to give me an error when I don't specify a namespace. This behavior stops the compiler from doing so, and this means my code is inconsistent in places, because I occasionally forget to specify the namespace when calling functions like f that are not declared globally anywhere.
Your implementation of f(nam::S*) is outside of the namespace of 'nam'
change:
void f(nam::S *){}
to:
void nam::f(nam::S *){}
(or just move the enclosing namespace bracket) and all should be fine.
if your call to f(&s) in the current namespace was intentional then you need to specify this by changing the function call to
::f(&s)
As was said in the comments, this is due to argument-dependent lookup. I guess now I'll have to figure out now if I want to always specify the namespace in my code where this would make it unnecessary, or never specify it.
Consider this sample of code:
#include <iostream>
namespace /* unnamed namespace */
{
struct Foo
{
int a;
int b;
};
}
struct Boo
{
Foo Foo; /* field name same as field type */
int c;
void print();
};
void Boo::print()
{
std::cout<<"c = "<<c<<std::endl;
std::cout<<"Foo "<<Foo.a<<" "<<Foo.b<<std::endl;
}
int main()
{
Boo boo;
boo.c=30;
boo.Foo.a=-21;
boo.Foo.b=98;
boo.print();
return 0;
}
Clang can compile it without errors.
Debian clang version 3.5.0-9 (tags/RELEASE_350/final) (based on LLVM 3.5.0)
Microsoft cl.exe compile it without errors. (I don't remember version. I use VS 2012)
And GCC: gcc version 4.9.2 (Debian 4.9.2-10):
main.cpp:14:6: error: declaration of ‘{anonymous}::Foo Boo::Foo [-fpermissive]
Foo Foo; /* field name same as field type */
^
main.cpp:5:9: error: changes meaning of ‘Foo’ from ‘struct {anonymous}::Foo’[-fpermissive]
struct Foo
^
What is good behavior of compiler? Why GCC can't compile it, but clang and cl.exe does? What C++ standard says?
Both are correct. Per §3.3.7/1
The following rules describe the scope of names declared in classes.
[..]
A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No diagnostic is required for a violation of this rule.
Neither are obligated to give an error, gcc chose to and clang apparently chose not to. It's conforming either way.
I wrote the following code:
#include <iostream>
using namespace std;
int main()
{
int v()
return 0;
}
I ran it in ideone, and it compiled successfully. I have the same code in file test1.cpp on my computer, I ran g++ test1.cpp and I got the following error:
./test1.cpp: In function ‘int main()’:
./test1.cpp:7:2: error: a function-definition is not allowed here before ‘return’
Why dose this happen? is this a bug?
I'm using linux mint, gcc version 4.7.
You are missing a semi-colon here:
int v()
^
should be:
int v() ;
which is a function declaration, not clear that was what was intended though. If you want to initialize v then the following would work:
int v(0) ;
or in C++11:
int v{0} ;
This is commonly known as C++'s most vexing parse. When you do something like
int f();
the compiler reads this as a function prototype, declaring a function f that returns an int. If you're using C++11, you should instead do
int f{}; // f initialized to 0
if you're not using C++11, make sure to initialize the variable right away.
You forgot the semicolon after
int v();
Ideone is using gcc 4.8.1 for your code (as you can see in your own link) while you are using 4.7
There are several difference regarding C++ 11 implementation, and apparently it is affected by the line that looks like a function delcaration.
I've been learning C++ and using the Terminal for the last couple of months. My code was compiling and running fine using g++ and C++11, but in the last couple of days it started giving errors and I have had problems compiling since. The only programs I can compile and run depend on older C++ standards.
The errors I first got related to #include < array > in the header file. Not sure why this happened, but I got around it by using boost/array instead. Another error I can't solve is with std::stoi. Both array and stoi should be in the C++11 standard library. I made the following simple code to demonstrate what's going on:
//
// stoi_test.cpp
//
// Created by ecg
//
#include <iostream>
#include <string> // stoi should be in here
int main() {
std::string test = "12345";
int myint = std::stoi(test); // using stoi, specifying in standard library
std::cout << myint << '\n'; // printing the integer
return(0);
}
Try to compile using ecg$ g++ -o stoi_trial stoi_trial.cpp -std=c++11
array.cpp:13:22: error: no member named 'stoi' in namespace 'std'; did you mean
'atoi'?
int myint = std::stoi(test);
~~~~~^~~~
atoi
/usr/include/stdlib.h:149:6: note: 'atoi' declared here
int atoi(const char *);
^
array.cpp:13:27: error: no viable conversion from 'std::string' (aka
'basic_string') to 'const char *'
int myint = std::stoi(test);
^~~~
/usr/include/stdlib.h:149:23: note: passing argument to parameter here
int atoi(const char *);
^
2 errors generated.
I also get these errors at compilation when using gcc or clang++ and with -std=gnu++11 (I guess they all depend on the same file structure). I also get the same error whether I specify std:: in the code, or if I specify using namespace std;
I worry that these issues arose because of the September Command Line Tools update via Xcode or because I installed boost and this somehow messed up my C++11 libraries. Hopefully there is a simple solution.
My system:
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-> dir=/usr/include/c++/4.2.1
Apple LLVM version 5.0 (clang-500.2.76) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin12.5.0
Thread model: posix
Thanks for any insight you can offer.
clang has a weird stdlib, you need to add the following flag when you compile
-stdlib=libc++
your snippet works on my mac with
g++ -std=gnu++11 -stdlib=libc++ test.cpp -o test
This answer describes the problem