I'm trying to get a reference to my class but it seems to is not declared.
This means it's undeclared:
#include <iostream>
using namespace std;
class time
{
private:
int sec;
int mins;
int hours;
public:
void setSeconds(int x)
{
sec = x;
}
int getSeconds()
{
return sec;
}
};
int main()
{
time to;
to.setSeconds(10000000);
cout << to.getSeconds() << endl;
return 0;
}
The error reads:
main.cpp: In function 'int main()':
main.cpp:29:10: error: expected ';' before 'to'
time to;
^
main.cpp:29:12: warning: statement is a reference, not call, to function 'time' [-Waddress]
time to;
^
main.cpp:29:12: warning: statement has no effect [-Wunused-value]
main.cpp:30:5: error: 'to' was not declared in this scope
to.setSeconds(10000000);
^
std::time is a function in the C++ standard library and, since you're using namespace std, that's being used by default instead of your class.
You can't even write ::time to reference yours, because your compiler's standard library implementation happens to include the old C ::time as well before wrapping it into namespace std.
Use some or all of these suggestions:
give your class a better, more unique name
write class time to reference your class (this ensures the type time is used, but is a poor hack)
use a namespace yourself to avoid all future ambiguities (this is recommended)
You should also stop using namespace std in general to help avoid as much trouble as possible, though it cannot directly aid you in this case.
Clang give a better error message:
time.cpp:29:5: error: must use 'class' tag to refer to type 'time' in this scope
time t;
^
class
/usr/include/time.h:192:15: note: class 'time' is hidden by a non-type declaration of 'time' here
extern time_t time (time_t *__timer) __THROW;
^
It isn't related to using namespace std. Rather the global time function is conflicting.
Related
This is a follow-up question from: constructing string from NULL?
The following:
void test(const std::string& s);
int main(){
test(NULL);
}
Fails when run, but is legal c++.
In order to try to catch some of those cases, as an alternative ive considering if std::string can be replaced in the following way:
#include <string>
namespace {
namespace std {
struct string : public ::std::string { //so far everything is good
};
}
}
int main ()
{
std::string hello;//failure: ambiguous symbol
return 0;
}
Gives the following error:
<source>(17): error C2872: 'std': ambiguous symbol
C:/data/msvc/14.22.27905/include\string(19): note: could be 'std'
<source>(7): note: or '`anonymous-namespace'::std'
<source>(17): error C2872: 'std': ambiguous symbol
C:/data/msvc/14.22.27905/include\string(19): note: could be 'std'
<source>(7): note: or '`anonymous-namespace'::std'
Compiler returned: 2
I guess it is not possible to make it resolve without writing a more (fully) qualified name ? but is it possible to write std::string in the global namespace and have it resolve to something else while ::std::string is a valid type.
Background: after some failed attempts with cppcheck and cpp core check im trying to find all cases of std::string str = 0 or NULL or nullptr - since those will fail at runtime. And I thought this might be a way forward.
I ended up modifying the basic_string template ala. basic_string(int) = delete;
basic_string(::std::nullptr_t) = delete; - this won't catch all cases but does indeed seem to catch the direct cases at least
Resolve std::string to something else than ::std::string - is it possible?
[...]
...as an alternative ive considering if std::string can be replaced in the following way...
As far as I know, it is not possible outside of your anonymous namespace scope because you have no way to resolve the ambiguity (not to my knowledge).
As you can see below, since you are inside the scope of the anonymous namespace, it will be fine:
#include <string>
namespace
{
namespace std
{
struct string : public ::std::string
{
};
}
std::string hello; // Fine
}
int main()
{
std::string hello2; // Cannot be something else that ambiguous
return 0;
}
But even worse, the problem is not about std::string itself but about the std namespace.
Indeed, outside of the scope of your anonymous namespace, every call of std becomes ambiguous too.This is the error pointed by the compiler. There are two std namespaces accessible as is from the global scope.
So the following example becomes broken:
#include <string>
#include <vector>
namespace
{
namespace std
{
struct string : public ::std::string
{
};
}
std::string hello; // Fine
}
int main()
{
std::vector<int> a; // FAIL: reference to 'std' is ambiguous
return 0;
}
To fix this ambiguity over accessing the original std namespace, you'll need to write it as follows:
::std::vector<int> a; // Fully qualified name: Only way to refer to the `::std` namespace
As you can see, it still does not solve the issue and even worse, it adds a huge inconvenience.
Therefore the morality is:
Do not hide an already existing type but create a distinct one instead.
In the same way, do not hide a namespace (by defining the same namespace into an anonymous one --> evil).
(I'm open to any improvement proposal of this answer)
Could you use this kind of solution : Rather than working on std::string, you work on the function that will cause the problem
#include <string>
void test(const std::string& s){
}
// add a new function which use a pointer :
void test (const char* _Nonnull s) {
test(std::string(s));
}
int main()
{
test(NULL);
return 0;
}
Then clang will generate a warning :
1 warning generated.
ASM generation compiler returned: 0
<source>:13:14: warning: null passed to a callee that requires a non-null argument [-Wnonnull]
test(NULL);
see https://godbolt.org/z/PujFor
Here is the code example:
namespace A
{
int k;
}
void k(int,int){/*dosomething*/}
int main()
{
using namespace A;
k(1,1);//ooop!k is ambiguous!
}
What happened? I thought it should not be ambiguous since they are different types. Why is it ambiguous? With int k it is not possible to do k(1,1).
So it has nothing to do with what the name actually is?Even if a name that is not a function type will also cause ambiguity when we use k(1,1) ,which is wrong in grammar because int k is not function?
Lookup of the name k is ambiguous because there are two matching declarations visible, ::k and ::A::k .
The exact rule can be found in the C++ Standard (N4659 [basic.lookup]/1):
Name lookup associates the use of a name with a set of declarations of that name. The declarations found by name lookup shall either all declare the same entity or shall all declare functions; in the latter case, the declarations are said to form a set of overloaded functions.
Looking up an unqualified name that is used for a function call has two stages:
Unqualified lookup of the name
Argument-dependent lookup of the name.
The unqualified name lookup rules, even when looking up a name that is being used for a function call, find any declaration of that name. (The rule is NOT that it only searches for function declarations of that name). This stage finds both ::k and ::A::k regardless of whether those are functions, ints, or whatever.
The argument-dependent lookup does have a rule that only function declarations are found for that part of the lookup. But that is not relevant to this code.
The relevant behaviour of the using directive is covered by [basic.lookup.unqual]/2 (edited by me to just show the parts relevant to this question):
For the purpose of the unqualified name lookup rules, the declarations from the namespace nominated by the using-directive are considered members of that enclosing namespace.
This clarifies that using namespace A; does not actually introduce the members of A into the scope of main(); but it means that when looking up a name in the global namespace (because that is the innermost enclosing namespace of the site of the using declaration), the names from A will also be found there.
There are three ways to resolve the ambiguity:
1st:
int main() {
A::k = 5;
::k( 1, 1 );
}
2nd:
int main() {
using namespace A;
A::k = 5;
::k(1, 1);
}
3rd:
namespace A {
int k;
}
namespace B {
void k( int, int ) { /* do something */ }
}
int main() {
using namespace A or B but not both!
if A then k = 5; okay && k(1,1); error
if B then k(1, 1); okay && k = 5; error
if both again ambiguous unless A::k = 5; || B::k(1,1);
return 0;
}
Due to the nature of ambiguity it doesn't truly pay to use using namespace A. And this is why it is considered bad practice to have using namespace std; either in the global scope or directly in the main function. It is okay to use it in a function or a member function of a class/struct as long as you don't conflict with any other library.
I ran this in my IDE visual studio 2017 CE and here is the compiler error:
1>------ Build started: Project: ChemLab, Configuration: Debug Win32 ------
1>main.cpp
1>c:\...\visual studio 2017\projects\chemlab\chemlab\main.cpp(17): error C2872: 'k': ambiguous symbol
1>c:\...\visual studio 2017\projects\chemlab\chemlab\main.cpp(8): note: could be 'void k(int,int)'
1>c:\...\visual studio 2017\projects\chemlab\chemlab\main.cpp(6): note: or 'int A::k'
1>Done building project "ChemLab.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
When you use the using namespace directive it will take everything that is in that namespace and make it visible to main. So now in main you have both the namespace A and the global namespace visible within main. Since you have both visible you now have 2 identifiers or symbols in the look up table named k. And when you call k(1, 1) it doesn't know which one you intended to choose.
This is no different than doing this:
main.cpp
#include <string>
class string {
public:
char* _chars;
};
int main() {
using namespace std;
string myString; // error ambiguous did you mean ::string or std::string?
return 0;
}
This might provide you with some more insight:
When the using directive is being used, don't think of the variable k and the function k as being declared in the same scope. They were previously declared in their own scope. The variable k is in ::A::k and the function void k(int,int){} is in ::k(int,int){}. In the main function when you apply the using namespace A; what happens here it takes every symbol after A:: and it kind of shifts it as if it were in the global :: scope for visibility. Now the compiler has to make a choice on the available symbols and sees I have a k and a k. Did you mean int k(){} or void k(int,int){}...
The ambiguity comes from the name. There is no way to overload a variable like you would a function/method, so there is a "clash" in the names.
In order to get the "k" that you want, you need to specify the namespace.
namespace A
{
int k;
}
void k(int, int) {/*dosomething*/ }
int main()
{
using namespace A;
::k(1, 1); // uses the global namespace
A::k = 5; // uses the namespace A
}
Or, to take the namespace out of the equation:
void k(int, int) {/*dosomething*/ }
void k(int, int, float) {}
int main()
{
int k;
// all of these are now ambiguous
k(1, 1);
k(1, 2, 0.4);
k = 5;
}
I have such pretty little code:
//example1
namespace
{
int a;
}
int a;
main()
{
a++;
return 0;
}
Of course, g++ 4.6.1 compiler can't compile it and outputs an error:
./temp.cpp: In function ‘int main()’:
./temp.cpp:10:5: error: reference to ‘a’ is ambiguous
./temp.cpp:6:5: error: candidates are: int a
./temp.cpp:2:9: error: int {anonymous}::a
It's all right!
But when I delete the reference to variable "a" within "main" function, the program is being compiled well:
//example2
namespace
{
int a;
}
int a;
main()
{
return 0;
}
1) Why does the g++ compiler allows the definition of variable "a", when in such case it disallows the references to it?
2) Is it just the g++ compiler's feature, and no other compiler is able to compile such code (example2)?
3) Does the g++ compiler have corresponding flags to interpret such code (example2) as faulty?
Thanks a lot for everyone!
The second example is valid because you can still access the global a from outside that translation unit.
The a in the anonymous namespace provides a definition for a variable that has internal linkage. The a at global namespace scope is a definition for a variable with external linkage. You can declare a extern int a; in a different translation unit and use it.
Just because you can't reference the a in the anonymous namespace from main doesn't mean the code is invalid.
The a in the anonymous namespace can still be referenced from within the anonymous namespace.
The global a can be referenced from everywhere (you'd have to use ::a in main to remove the ambiguity).
The short answer is "because there's nothing illegal about it". It's just using a in main that is wrong. If you use ::a it will give you the global one (without the namespace).
And you can use a inside the namespace itself, e.g. we could have a function:
namespace {
int a;
int work_with_a()
{
a += 2;
return a;
}
}
int a;
int main()
{
::a++;
int b = work_with_a();
cout << ::a + b;
}
#include<iostream>
#include<stdlib.h>
#include<string.h>
using namespace std;
class div
{
int x,y;
public:
class dividebyzero
{
};
class noerror1
{
};
div(){};
div(int a,int b)
{
x=a;
y=b;
}
void error1()
{
if(y==0)
throw dividebyzero();
else
throw noerror1();
}
int divide()
{
return (x/y);
}
};
class naming
{
char name[32];
public:
class nullexception
{
};
class noerror2
{
};
naming(char a[32])
{
strcpy(name,a);
}
void error2()
{
if(strcmp(name,"")==0)
throw nullexception();
else
throw noerror2();
}
void print()
{
cout<<"Name-----"<<name<<endl;
}
};
int main()
{
div d(12,0);
try
{
d.error1();
}
catch(div::dividebyzero)
{
cout<<"\nDivision by Zero-------Not Possible\n";
}
catch(div::noerror1)
{
cout<<"\nResult="<<d.divide()<<endl;
}
naming s("Pankaj");
try
{
s.error2();
}
catch(naming::nullexception)
{
cout<<"\nNull Value in name\n";
}
catch(naming::noerror2)
{
s.print();
}
return 0;
}
On compiling this program I am getting following error
pllab55.cpp: In function ‘int main()’:
pllab55.cpp:61:6: error: expected ‘;’ before ‘d’
pllab55.cpp:64:3: error: ‘d’ was not declared in this scope
pllab55.cpp:72:22: error: ‘d’ was not declared in this scope
pllab55.cpp:74:20: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
Before declaring the class naming everything was running fine.It is after declaration of naming these error started to occur. I am new to C++. Please explain me in details. Thanks in advance.
There is already an std::div in the standard namespace and since you use a using namespace directive instead of declaration it imports all the symbols in std namespace to your current scope. So perhaps renaming the div class shall do the trick for you.
I tried renaming it and it does work indeed.
So either rename your class or wrap it in your own namespace so it does not conflict with std::div
Your class div shares the same name as std::div. When you do #using namespace std, the result is that each class in the std namespace is imported into your current scope, meaning that std::div is now essentially called div. If you see, that means you now have two classes called div in the same scope, your own and the std class.
By the way, you should avoid the using namespace syntax and rather use the full qualifier of the class (e.g. std::cout).
Your div class is conflicting with std::div so either rename yours or put put your div class in a different namespace.
namespace me {
struct div{};
}
me::div d;
I gave (a slight variant of) your code a try in gcc and I got the following error:
/usr/include/stdlib.h:780: error: too few arguments to function 'div_t div(int, int)'
You're trying to override a name from a standard library and experience the conflict of a class and a function having the same name, I'm afraid.
as a general rule of thumb, if you encounter such issues, try to reduce your code as much as possible. For instance, I reduced it down to
#include<stdlib.h>
class div {
public:
div (int a, int b) { }
};
int
main () {
div d (12, 0);
return 0;
}
which still shows your error (at least the first one - the others are followup errors).
This lets you also reduce possible assumptions about the reason for the error - as you see, your new class "naming" does not have to do anything with the error you see.
When I now additionally remove the include, the error does not show up anymore, which lets me suspect some naming clash with some symbol from stdlib.h. After renaming the class "div" to something else (like "CDiv"), it works.
// main.cpp
const double MAX = 3.5;
namespace ns
{
const int MAX = 3;
}
int main()
{
}
will this cause redefinition error?
I'm referring to this MSDN page, which says in the Remarks section that this is an error.
Update: I think I may miss one important statement when copying around the code.
using ns::MAX;
No - I don't see how that code would cause a redefinition error.
And in fact, you can compile it and see for yourself.
EDIT: Following up now that you've supplied the link to the MSDN page you mentioned...
That MSDN page is talking about name clashes in the context of a using directive:
If a local variable has the same name as a namespace variable, the
namespace variable is hidden. It is an error to have a namespace
variable with the same name as a global variable.
Here's an example of a local variable hiding a namespace variable that's been brought into scope by a using directive:
namespace ns
{
const int MAX = 3;
}
using namespace ns;
int main()
{
int MAX = 4; // local
int test = MAX; // test is 4, because the local variable is used
// as the namespace variable is hidden
}
The inclusion of the using directive brings all of the names declared within the ns namespace into scope. However, when I assign the value of MAX to test, it's the local variable MAX that is used in the assignment because the namespace variable MAX is hidden. The local variable takes precedence and hides the namespace variable.
Now here's an example of a clash between a namespace variable and a global variable.
Consider this amended piece of code (and you can see it compile here):
const double MAX = 3.5;
namespace ns
{
const int MAX = 3;
}
using namespace ns;
int main()
{
int test = MAX;
}
Again, the using directive brings ns:MAX into scope, and the global variable MAX is also in scope.
When I go to use the variable called MAX in main(), the compiler reports an error because the name MAX is now ambiguous: it has no way of knowing which MAX we are referring to, as there are two non-local MAXs to choose from: neither has any precedence.
prog.cpp: In function ‘int main()’:
prog.cpp:13: error: reference to ‘MAX’ is ambiguous
prog.cpp:2: error: candidates are: const double MAX
prog.cpp:6: error: const int ns::MAX
prog.cpp:13: error: reference to ‘MAX’ is ambiguous
prog.cpp:2: error: candidates are: const double MAX
prog.cpp:6: error: const int ns::MAX
They wouldn't because one is in file scope and the other in namespace scope.