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.
Related
If I have
namespace foo {
inline int bar() {
return 1119;
}
}
__attribute__((deprecated)) inline int bar() {
return 138;
}
in header.h and
#include "header.h"
#include <iostream>
int main() {
int x = bar();
int y = foo::bar();
std::cout << x << std::endl;
std::cout << y << std::endl;
}
in source.cpp, then
g++ source.cpp -o deprecated-test
results in
source.cpp: In function ‘int main()’:
source.cpp:5:17: warning: ‘int bar()’ is deprecated [-Wdeprecated-declarations]
int x = bar();
^
In file included from source.cpp:1:
header.h:7:40: note: declared here
__attribute__((deprecated)) int bar() {
^~~
source.cpp:5:17: warning: ‘int bar()’ is deprecated [-Wdeprecated-declarations]
int x = bar();
^
In file included from source.cpp:1:
header.h:7:40: note: declared here
__attribute__((deprecated)) int bar() {
(on Ubuntu 18.10 with g++ 8.2.0).
Why does the deprecated warning print twice?
Heading off some suggestions that would be unhelpful:
[[deprecated]]:
I know with C++14 on you can use the [[deprecated]] attribute, but I need to work with C++11.
Declaration vs. definition: The docs seem to imply it should be used with function declaration rather than definition, but
I need to define the functions inline in a header rather than declare in the header and define in source files; and
Trying this approach didn't stop the warning from printing twice anyway.
As per the documentation of GCC 8.2.0:
The deprecated attribute results in a warning if the function is used anywhere
in the source file. This is useful when identifying functions that are expected
to be removed in a future version of a program. The warning also includes the
location of the declaration of the deprecated function, to enable users to easily
find further information about why the function is deprecated, or what they
should do instead. Note that the warnings only occurs for uses...
There should be only one warning and not two. So this is a bug in GCC.
There is a related bug for Type attributes (rather than Function attributes) titled: C/C++ __attribute__((deprecated)) does not appear to wrap declarations as implied from the doc.
It has been confirmed as a bug.
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 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.
Can someone please explain below output:
#include <iostream>
using namespace std;
namespace A{
int x=1;
int z=2;
}
namespace B{
int y=3;
int z=4;
}
void doSomethingWith(int i) throw()
{
cout << i ;
}
void sample() throw()
{
using namespace A;
using namespace B;
doSomethingWith(x);
doSomethingWith(y);
doSomethingWith(z);
}
int main ()
{
sample();
return 0;
}
Output:
$ g++ -Wall TestCPP.cpp -o TestCPP
TestCPP.cpp: In function `void sample()':
TestCPP.cpp:26: error: `z' undeclared (first use this function)
TestCPP.cpp:26: error: (Each undeclared identifier is reported only once for each function it appears in.)
I have another error:
error: reference to 'z' is ambiguous
Which is pretty clear for me: z exists in both namespaces, and compiler don't know, which one should be used. Do you know? Resolve it by specifying namespace, for example:
doSomethingWith(A::z);
using keyword is used to
shortcut the names so you do not need to type things like std::cout
to typedef with templates(c++11), i.e. template<typename T> using VT = std::vector<T>;
In your situation, namespace is used to prevent name pollution, which means two functions/variables accidently shared the same name. If you use the two using together, this will led to ambiguous z. My g++ 4.8.1 reported the error:
abc.cpp: In function ‘void sample()’:
abc.cpp:26:21: error: reference to ‘z’ is ambiguous
doSomethingWith(z);
^
abc.cpp:12:5: note: candidates are: int B::z
int z=4;
^
abc.cpp:7:5: note: int A::z
int z=2;
^
which is expected. I am unsure which gnu compiler you are using, but this is an predictable error.
You get a suboptimal message. A better implementation would still flag error, but say 'z is ambiguous' as that is the problem rather than 'undeclared'.
At the point name z hits multiple things: A::z and B::z, and the rule is that the implementation must not just pick one of them. You must use qualification to resolve the issue.
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.