I am new to namespaces and was trying this from C++ Primer
#include<iostream>
namespace Jill
{
double bucket;
double fetch;
struct Hill{ };
}
double fetch;
int main()
{
using namespace Jill;
Hill Thrill;
double water = bucket;
//double fetch; //<<<<<<<<<<<<//
std::cin>> fetch;
std::cin>> ::fetch;
std::cin>> Jill::fetch;
std::cout<<"fetch is "<<fetch;
std::cout<<"::fetch is "<< ::fetch;
std::cout<<"Jill::fetch is "<< Jill::fetch;
}
int foom()
{
Jill::Hill top;
Jill::Hill crest;
}
When the line marked //<<<<<<<<<<<<// is not commented I get expected results. i.e. the
local variable hides the global and Jill::fetch. But when I comment it out, there are 2 fetch left . global fetch and Jill::fetch. And the compiler gives the error
namespaceTrial1.cpp:17:13: error: reference to ‘fetch’ is ambiguous
namespaceTrial1.cpp:9:8: error: candidates are: double fetch
namespaceTrial1.cpp:5:9: error: double Jill::fetch
namespaceTrial1.cpp:20:26: error: reference to ‘fetch’ is ambiguous
namespaceTrial1.cpp:9:8: error: candidates are: double fetch
namespaceTrial1.cpp:5:9: error: double Jill::fetch
My question is why does the compiler get confused this lead to ambiguity? Why does it not assume fetch as just Jill::fetch , since I have added using namespace Jill at the start of main()
If I use declarative using Jill::fetch; at the start of main, the issue gets solved. because using Jill::fetch makes it as if it has been declared at that location. So, its like there is a local fetch variable. [Am i correct?] Why does using declaration behave as if the variable was declared at that location and using directive doesnt?
When you declare a local variable shadowing a global/namespace variable, you explicitly tell the compiler about that. However, when you are using using the variables of the namespace doesn't actually end up in the local scope.
From the specification (section 7.3.4, point 3):
A using-directive does not add any members to the declarative region in which it appears.
Also (from same section, point 6):
If name lookup finds a declaration for a name in two different namespaces, and the declarations do not declare the same entity and do not declare functions, the use of the name is ill-formed.
The using directive modifies name lookup in a way that isn't exactly intuitive to most programmers. The standard says this in [namespace.udir]p2:
During unqualified name lookup (3.4.1), the names appear as if they were declared in the nearest enclosing namespace which contains both the using-directive and the nominated namespace.
This wording means that names from the namespace do not appear in the current scope, but in some outer scope. In your example the using directive is in the function which is in the global namespace, and the Jill is also in the global namespace, so the names from Jill appears as if they are in the global namespace. (As Joachim said, the names aren't actually introduced there, so they don't immediately conflict with existing names and you only get ambiguous lookups when you actually use them.)
This is a simple case and the compiler gives you an error, which is good. It can actually get more complicated than that.
namespace Outer {
namespace Mid1 { int i = 1; }
namespace Mid2 {
namespace Tricky {
int i = 2;
namespace Inner {
void f() {
using namespace Mid1;
std::cout << i;
}
}
}
}
}
This will output 2, not 1, even though you had the using directive right next to the line referring to i. But the nearest enclosing namespace that contains both Mid1 and the using directive is Outer, so Mid1::i acts as if it was declared in Outer. If you had an Outer::i it would be shadowed by Tricky::i, and Mid1::i fares no better.
An easy solution is to ban using directives and only use using declarations and namespace aliases. They're far more intuitive.
using namespace will not give priority to names it imports resulting in what you already observed.
Getting ambiguity error here is language design decision: it would be rather dangerous for such prioritization to exist. Imagine that the Jill namespace is a large one maintained by several developers probably from different organization. You have no or limited control to its contents and still changes to it might silently change the meaning of your program.
[basic.scope.declaration] says that a local variable hides the global, after it's declaration
int j = 24;
int main() {
int i = j, j;
j = 42;
}
the identifier j is declared twice as a name (and used twice). The declarative region of the first j includes the entire example. The potential scope of the first j begins immediately after that j and extends to the end of the program, but its (actual) scope excludes the text between the , and the }. The declarative region of the second declaration of j (the j immediately before the semicolon) includes all the text between { and }, but its potential scope excludes the declaration of i. The scope of the second declaration of j is the same as its potential scope.
This explains why there isn't an error when you declare a local variable.
When the local variable is not declared, then you have a name clash. The compiler can not decide which fetch to pick, and throws an error.
Related
I wrote the following code :
#include<bits/stdc++.h>
using namespace std;
int lengthOfLastWord(string A) {
int m= A.size();
int i=0;
while(i<m)
{
if(A[i]==' ')
{
int count=0;
i++;
while(A[i]!=' ')
{
count++;
i++;
}
}
else
i++;
}
return count;
}
int main()
{
string A;
getline(cin,A);
cout<<lengthOfLastWord(A);
}
But it is showing the following error
error: cannot resolve overloaded function ‘count’ based on conversion to type ‘int’
I am unable to understand why is it showing this error and what should I do to fix it.
Please help me.
Thankyou
Inside the if scope, your count variable is colliding with (technically "shadowing") std::count. However, your local count does not exist in the scope of your return statement, so the compiler is trying to use the only count that it knows about at that point, which is std::count.
This is a great example of why using namespace std and #include<bits/stdc++.h> are both bad ideas. If proper includes and namespaces were used, this code would have given you a much clearer compile error:
error: 'count' was not declared in this scope
The most direct reason is because your count variable is defined in the if scope, and not available in the scope of return statement.
However, the error you are seeing is confusing, since you have using namespace std in your code, and it makes completely unrelated (for your purposes) function std::count visible everywhere in your program, including your return statement. From the compiler perspective, you are trying to return a pointer to std::count, but since this function is overloaded template, compiler doesn't know which one you are trying to return - thus the phrasing of the errror.
If you remove the using namespace std from your code, which you should have never had in the first place, your code will still fail to compile, but error message would be way more easier to understand.
One solution is to rename your count variable to something else like total.
The compiler is considering std::count function instead of the count variable which is int.
When I run this code, it displays 6...
#include <iostream>
namespace X {
int p = 5;
}
using namespace X;
int p = 6;
int main()
{
std::cout << ::p;
return 0;
}
However, when I run this code, it displays 5...
#include <iostream>
namespace Y {
int p = 16;
}
namespace X {
int p = 5;
using namespace X;
}
int main()
{
std::cout << X::p;
return 0;
}
Can anyone explain what's happening there? Why am I not getting any error about ambiguity?
First, your question itself. In the first example, you use...
std::cout << ::p;
That prepended :: resolves namespaces in a specific order, starting with the local namespace. (See this answer). Thus, it looks for p globally, locally, and then in an external namespace (X). Because it found p locally, it stops looking.
In the second example, you are explicitly resolving your namespace:
std::cout << X::p;
Thus, there's no search order to be bothered with. It is just going to look for p in the namespace X, and fail otherwise.
This leads to the second problem: you appear to be confusing the purpose of the using namespace keywords. Those are intended to enable you to use a more shorthand approach of resolving to a namespace, instead of always using the fully qualified name (x::p).
However, the computer will still look in the local namespace first, and THEN the using namespaces in the order they are found. As always, once the computer finds the thing named in a namespace, it stops looking.
This leads to a major principle in C++: don't use using namespace! There are exceptions, but you'll pick up on those as you work. The issue comes down to ambiguity as to what namespace something will be coming from, which is exactly the problem you described.
For example, imagine you define the namespaces X and Y in separate classes, and then you simply have the following...
#include "x.hpp"
#include "y.hpp"
using namespace x;
using namespace y;
int main()
{
std::cout << p << std::endl;
}
Where'd p come from? Looking at x.hpp and y.hpp, you see that BOTH havep, so which one is used? And then, what if you addusing namespace z;above them? Now you have to check ifzhasp`. ARGH!
(See this answer for more information on namespace resolution.)
It is important to note that, as far as the compiler/linker are concerned, there is no ambiguity. It has an implicit resolution order to handle that. The ambiguity is all on the coder.
Even worse, what if you define q locally, without realizing that x or y have a q as well? What will it resolve to?
This is a situation you never want to create! Borrowing from Tim Peter's Zen of Python (albeit, different language, but some of the principles therein are true in most languages)...
Explicit is better than implicit.
So, how can we write this to be less wibbly-wobbly timey-wimey?
Drop using namespace. The only time you should even touch this is if you are using a bunch of stuff from one namespace, and virtually nothing from anywhere else. (You'll notice most C++ programmers won't even do using namespace std;)
Use the fully qualified name on anything you use sparingly-to-moderately. For example, x::p.
If you use something a lot, use the command using x::p at the top of the file. This resolves p to namespace x, without confusing everything else.
In short, you should be able to tell, at a glance, what namespace everything comes from. Never create a situation of ambiguity and implicit resolution; only bugs and pain lie that way.
When I run this below code snippet, the output is a is 6. But since I have used namespace n1, which also has variable by name "a", shouldn't the output be a is 5. Am I missing something ?
#include <iostream>
using namespace std;
namespace n1{
int a = 5;
}
int main(void){
int a = 6;
using namespace n1;
cout<<"a is "<<a<<endl;
return 0;
}
But if I use fully qualified name in cout i.e cout<<"a is "<<n1::a; the output is as expected i.e. 5. What is the purpose of using namespace ?
The using directive is a hint to the compiler for places where it should search the name a.
This way, the name look-up will be done in this order:
First search for a in the local scope
If a isn't found, search in the namespace n1
If there's still no a found, look in the global namespace
Without the using directive you provided, the second step wouldn't be performed.
In your case, as there is actually a variable (but it could be anything, we're talking about names) named a, it doesn't go any further.
The rule is simple:
"Local variables always shadow/hide the variables in other namespaces or global variables with same name."
Within the scope in which local variable a is declared, the using directive has no effect w.r.t the symbol name a. It still does import all the symbol names from namespace n1 within the current scope but the local variable a still hides n1::a. So n1::a is simply not visible and you need to use the fully qualified name for it.
when a variable is defined in the local namespace (a in main is in your local namespace) it will prefer it.
So in this case you must tell it (I would like the a from the n1 namespace n1::a)
if you remove the a it will work as expected...
I'm currently getting the following compile errors:
In function 'int main()':
error: expected primary-expression before '>' token
error: missing template arguments before 'i'
error: expected ';' before 'i'
error: 'i' was not declared in this scope
I've highlighted the line the first error flags on in the code block below:
// test highscoresfilemanager reading & writing
/*
HighScorePair paira("holly", 10);
HighScorePair pairb("carl", 20);
*/
list< HighScorePair > list;
//list.push_back(paira); list.push_back(pairb);
HighScoresFileManager::GetInstance()->ReadFileToList(list);
list< HighScorePair >::iterator i; //ERROR FLAGS HERE ODDLY
for(i = list.begin(); i != list.end(); ++i)
std::cout << (*i).playerName << " " << (*i).playerScore << std::endl;
I left in some commented out text I was using to test something previously because I'm certain that that commented out text works perfectly and if it works I don't see why the new code I've added wouldn't work, I'm not using any new classes or anything, I've just tried to get an iterator setup.
I feel quite rude as I think I'm basically asking someone to check my syntax, I keep reading over it and thinking I must be missing a colon somewhere or something but I just can't see what the issue is! A new eye would be greatly appreciated! I appreciate you might want more code (which I can provide) but like I said if the stuff commented out worked then I think the new code should to.
Don't call your variable list.
First, I'm supposing that you've got a using namespace std; somewhere;
that's generally not a good idea. But the basic problem would remain
(albeit not for list, since you'd write `std::list): you've defined a
local variable with the same name as a symbol in a larger scope; the
local variable hides that symbol from its point of declaration until it
goes out of scope. So up until the line:
list< HighScorePair> list;
, list refers to the symbol you pulled into global scope with using
namespace std;, and after that line, until the end of the block, it
refers to the variable you have just defined here. The variable is
not a template, and its type doesn't support <, so list < isn't
legal.
As a general rule, I would recommend against hiding names. It leads to
confusion. Also: type names should be unqualified nouns (like list),
variable names should be qualified nouns (like currentList). At least
in principle; I can see cases where such a rule would be overkill.
Guess you wrote using namespace std; When you call variable that associate with function in std:: it will throw compile error. Just use exact namespace when define variables ( std::list ).
Alright, I wanna know why this code is working, I just realized that I have two variables with the same name within the same scope.
I'm using g++ (gcc 4.4).
for(int k = 0 ; k < n ; k++)
{
while(true)
{
i = Tools::randomInt(0, n);
bool exists = false;
for(int k = 0 ; k < p_new_solution_size ; k++)
if( i == p_new_solution[k] )
{
exists = true;
break;
}
if(!exists)
break;
}
p_new_solution[p_new_solution_size] = i;
p_new_solution_size++;
}
The k in the inner for loop shadows (or hides) the k in the outer for loop.
You can declare multiple variables with the same name at different scopes. A very simple example would be the following:
int main()
{
int a; // 'a' refers to the int until it is shadowed or its block ends
{
float a; // 'a' refers to the float until the end of this block
} // 'a' now refers to the int again
}
Alright, I wanna know why this code is working, I just realized that I have two variables with the same name within the same scope.
You seem confused about scopes. They're not "within the same" scope... the for loop's k has it's own nested/inner scope. More importantly, to see why the language allows it, consider:
#define DO_SOMETHING \
do { for (int i = 1; i <= 2; ++i) std::cout << i << '\n'; } while (false)
void f()
{
for (int i = 1; i <= 10; ++i)
DO_SOMETHING();
}
Here, the text substituted by the macro "DO_SOMETHING" gets evaluated in the same scope as i. If you're writing DO_SOMETHING, you may need its expansion to store something in a variable, and settle on the identifier i - obviously you have no way of knowing if it'll already exist in the calling context. You could try to pick something more obscure, but you'd have people using such convoluted variable names that their code maintainability suffered, and regardless sooner or later there would be a clash. So, the language just lets the inner scopes introduce variables with the same name: the innermost match is used until its scope exits.
Even when you're not dealing with macros, it's a pain to have to stop and think about whether some outer scope is already using the same name. If you know you just want a quick operation you can pop it an indepedent (nested) scope without considering that larger context (as long as you don't have code in there that actually wants to use the outer-scope variable: if you do then you can sometimes specify it explicitly (if it's scoped by namespaces and classes, but if it's in a function body you do end up needing to change your own loop variable's name (or create a reference or something to it before introducing your same-named variable)).
From the standard docs, Sec 3.3.1
Every name is introduced in some portion of program text called a declarative region, which is the largest part of the
program in which that name is valid, that is, in which that name may be used as an unqualified name to refer to the
same entity. In general, each particular name is valid only within some possibly discontiguous portion of program text
called its scope. To determine the scope of a declaration, it is sometimes convenient to refer to the potential scope of
a declaration. The scope of a declaration is the same as its potential scope unless the potential scope contains another
declaration of the same name. In that case, the potential scope of the declaration in the inner (contained) declarative
region is excluded from the scope of the declaration in the outer (containing) declarative region.
It might sound confusing in your first read, but it does answer your question.
The potential scope is same as the scope of the declaration unless another (inner) declaration occurs. If occurred, the potential scope of the outer declaration is removed and just the inner declaration's holds.
Hope am clear and it helps..
Because you are allowed to have two variables of the same name within the same scope, but not within the same declaration space. The compiler takes the most-local variable of the appropriate name, similar to how you can 'hide' global variables of name X with a member variable of name X. You should be getting a warning though.
In C/C++ the variable scope is limited by the braces so the following code is valid for the compiler:
int k()
{
int k;
{
int k;
{
int k;
}
}
}