C++ getline() doesn't require namespace declaration - c++

Why is getline() from header string in local scope and can be used:
#include <iostream>
#include <string>
int main() {
std::string str;
getline(std::cin, str);
std::cout << str << "\n";
return 0;
}
That works with gcc. But why? It is defined in header string, which should required me to use std::getline() instead of getline().

You're experiencing Argument Dependent Lookup (ADL, and also referred to as Koenig Lookup). Since one or more of the arguments is a type defined in the std namespace, it searches for the function in the std namespace in addition to wherever else it would search. I point you to Stephan T. Lavavej's video to learn more about it and name lookup in general.

Related

Where is getline() function coming from?

I am starting learning C++ a little while ago.
Came to know about header files and preprocessor statements.
I know that std::cin and std::cout are the objects/Function is declared in standard library IOSTREAM.
But when taking input as a string and to read the whole line. We have to getline() function or at least the instructor is using it in the video.
Now I have checked on the internet and most of the sites are showing that getline() is defined under STRING file/Library. But the thing is my program is working perfectly fine even without including the string file. So what I am missing.? or doing something wrong. and if you can please also explain how getline function is working. and also please what's the actual difference between using namespace std, and using std::
Thank you
#include <iostream>
int main()
{
std::string str;
std::cout << "Please enter your name: \n";
getline(std::cin, str);
std::cout << "Hello, " << str
<< " welcome to GfG !\n";
return 0;
}
You have to include the header <string> to use the function std::getline. It is implementation defined whether the header <iostream> includes the header <string>.
In this call using unqualified name getline
getline(std::cin, str);
the compiler applies the argument dependent lookup ADL (the first argument std::cin is defined in the namespace std::) and finds the corresponding name std::getline in the namespace std::.

Different use of scope operator

To transform a string and make it lowercase, we might do the following:
#include <iostream>
#include <algorithm>
#include <string>
#include <cctype>
using namespace std;
int main()
{
string str("Sample STRING");
cout << str << endl;
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
cout << str << endl;
return 0;
}
I know what std::transform is all about; but what's the scope operator :: doing in front of the function tolower?
If I remove the scope operator then the compiler complains of a function mismatch. If I add std in front of the :: operator then the compiler also complains of a function mismatch. What is the purpose of the scope operator in front of tolower? I don't know what it's called, and I searched everywhere for an explanation but to no avail.
You should #include <algorithm> to use std::transform.
The tolower function you want is defined in ctype.h or cctype. You should include one of these headers. The former declares tolower in the global namespace; the latter declares it in the std namespace.
It's likely that without the ::, you're picking up the function template std::tolower declared in the <locale> header. Of course, this only happens because you have using namespace std;. This is a particular example of how using namespace std; can be dangerous.
The :: with nothing on the left means the name to the right will be "looked up in global scope" and will find the global tolower rather than std::tolower. (Therefore, you should #include <ctype.h> to make sure you get the global declaration.)
:: without a left side bypasses looking in all accessible sub-scopes and forces the use of the root (or global) scope.

Why can I call getline without using std::getline?

I am following the C++ Primer book and trying out all the code examples.
I am intrigued by this one:
#include <iostream>
#include <string>
using std::string;
using std::cin;
using std::cout;
using std::endl;
int main()
{
string line;
while (getline(cin,line))
cout << line << endl;
return 0;
}
Before compiling this code I was guessing that the compilation would fail, since I am not using
while (std::getline(cin,line))
Why is getline in the global namespace?
As I understand, this should only happen if I used
namespace std;
or
using std::getline;
I am using g++ version 4.8.2 on Linux Mint Debian Edition.
This is argument dependent lookup.
Unqualified lookup (what you are doing when you just call getline() instead of std::getline()) will start by trying to do normal name lookup for getline. It will find nothing - you have no variables, functions, classes, etc. in scope with that name.
We will then look in the "associated namespaces" of each of the arguments. In this case, the arguments are cin and line, which have types std::istream and std::string respectively, so their associated namespaces are both std. We then redo lookup within namespace std for getline and find std::getline.
There are many more details, I encourage you to read the reference I cited. This process is additionally known as Koenig lookup.
Since std::getline() for std::string is defined in the header I would have to say that Argument-dependent lookup is coming into play.
When you use getline(cin, line), it is equivalent to using getline(std::cin, line) since you have the line:
using std::cin;
Using Argument Dependent Lookup (ADL), the compiler is able to resolve that function call to std::getline(std::cin, line). You can read more about ADL at http://en.cppreference.com/w/cpp/language/adl.

Functions in namespace std accessible in global scope

Under some situations, it seems like I can access functions that should be in the std namespace without a using or std:: qualifier. So far, I've only seen this occur with functions from the algorithm library.
In the following example, I expect all_of() to be in the std namespace, but this code compiles without error in VS2013 (Microsoft Compiler 18).
#include <iostream>
#include <string>
#include <algorithm>
int main() {
const std::string text = "hey";
std::cout << all_of(begin(text),end(text),islower);
return 0;
}
Changing std::cout to cout without adding a using namespace std or using std::cout generates an "undeclared identifier" error as expected.
What's going on here?
This probably happens due to Argument-Dependent Lookup. The iterator returned by begin(text) and end(text) is probably a class defined in namespace std (or nested in a class in namespace std), which makes namespace std associated with it. Looking up unqualified names for function calls looks into associated namespaces, and finds all_of there.
By the way, this is exactly the same reason why calling begin(text) works, even though the function template begin() is defined in namespace std. text is a std::basic_string, so std is searched.

Namespace using declaration (C++ Primer - Stanley Lipmann)

Anyone can help me to understand this statement found in chapter 3 (Library Types) by Stanley Lipmann?
"Using an unqualified version of a namespace name without a using declaration is an error, although some compilers may fail to detect this error"
I'm having such hard time understanding the semantics of his sentence (english).
Is he trying to say something like the below scenario?
int main() {
xx::yy
}
where xx is a namespace not defined using the "using" statement and yy is a member?
Example:
cout is a name of the std namespace. The unqualified name is cout. The qualified name is std::cout. It is an error to use the unqualified name(cout) without a using declaration beforehand. You can use either one of the two following declarations:
// This brings in the entire std namespace
using namespace std;
OR
// This only brings in cout. You would still need to qualify other names,
// such as cin, endl, etc...
using std::cout;
What he's saying is that the following code should not compile:
#include <iostream>
void foo() {
cout << "This is an error!" << endl;
}
The cout and endl names are not defined right now. They're declared as std::cout and std::endl, and in order to use them, you can do one of a few things:
#include <iostream>
void foo() {
std::cout << "This, I think, is the best way to do it." << std::endl;
}
Using the fully qualified name prevents collisions later on: you'll never have something else called std::cout.
#include <iostream>
void foo() {
using std::cout;
using std::endl;
cout << "This is pretty good." << endl;
}
Having the using statements specify the exact names you're using, and having the using statements in the function, can save some typing and makes collisions pretty unlikely.
#include <iostream>
using namespace std;
void foo() {
cout << "This works, but isn't good." << endl;
}
Importing the entire std namespace makes it pretty likely that you'll end up having a function named the same as an std function.. You might discover that as soon as you write it, or you might write your function and then later include the header file with the std version of the function, at which point your application will mysteriously break.
A namespace name is the name of a namespace.
namespace A {
}
namespace B = A;
The statement says that using a namespace name without a using declaration is an error. But that's not true: The above code is fine, still using the namespace-name A as an unqualified name.
Probably it should say the following, to convey its meaning
"Using an unqualified version of a namespace member name without a using declaration
outside the scope of the namespace is an error, although some compilers may fail to
detect this error"
Mentioning the scope is important. The following, for example, is fine too, even though it uses the unqualified version of a namespace member name
namespace A {
int x;
int &y = x; // x is an unqualified name
}
Books should be careful to try and not use slippery language. And even outside the scope of the namespace, the above sentence is not entirely correct because you can also extend the scope of x by a using directive. Using declarations aren't the only way to name a namespace member outside the namespace using an unqualified name.