Show Lecture.SymbolAmbiguity as a slide show.
CS253 Symbol Ambiguity
or
“Them there namespacies is trickier then I done thought!”
% cat ~cs253/Example/version.cc
#include <iostream>
int main() {
std::cout << __cplusplus << '\n';
}
% g++ -std=c++98 -Wall ~cs253/Example/version.cc && ./a.out
199711
% g++ -std=c++11 -Wall ~cs253/Example/version.cc && ./a.out
201103
% g++ -std=c++14 -Wall ~cs253/Example/version.cc && ./a.out
201402
% g++ -std=c++17 -Wall ~cs253/Example/version.cc && ./a.out
201703
- __cplusplus is the long int YYYYMM of the C++ standard in use.
- Released in 1997, ratified in 1998?
What version do we use?
It’s easy to tell which version of the standard is in use:
cout << __cplusplus / 100;
2017
#include <iostream>
#include <string>
#include <utility>
using namespace std;
void move(const string &s) {
cout << "moving " << s << '\n';
}
int main() {
cout << __cplusplus << '\n';
move("umbrella");
}
199711
moving umbrella
#include <iostream>
#include <string>
#include <utility>
using namespace std;
void move(const string &s) {
cout << "moving " << s << '\n';
}
int main() {
cout << __cplusplus << '\n';
move("umbrella");
}
201103
Only changed -std=c++98
to -std=c++11
, but the output changed! Why?
The function move was introduced in C++11. It’s a better match
for a const char * than void move(const string &)
.
#include <iostream>
#include <string>
#include <utility>
using namespace std;
void move(const string &s) {
cout << "moving " << s << '\n';
}
int main() {
cout << __cplusplus << '\n';
move("umbrella");
}
201103
- C++ 11’s std::move is a better match for
"umbrella"
.
- New compiler, different behavior. 😱
Explicit std::
, C++ 98
#include <iostream>
#include <string>
#include <utility>
void move(const std::string &s) {
std::cout << "moving " << s << '\n';
}
int main() {
std::cout << __cplusplus << '\n';
move("umbrella");
}
199711
moving umbrella
- Some avoid using namespace, and sprinkle their code with
std::
.
- It’s not pretty.
Explicit std::
, C++ 11
#include <iostream>
#include <string>
#include <utility>
void move(const std::string &s) {
std::cout << "moving " << s << '\n';
}
int main() {
std::cout << __cplusplus << '\n';
move("umbrella");
}
201103
moving umbrella
Selective using, C++ 98
#include <iostream>
#include <string>
#include <utility>
using std::cout;
using std::string;
void move(const string &s) {
cout << "moving " << s << '\n';
}
int main() {
cout << __cplusplus << '\n';
move("umbrella");
}
199711
moving umbrella
- Some people apply selective using declarations.
- It’s not pretty, either, but at least the clutter is all together
and easy to skip over.
Selective using, C++ 11
#include <iostream>
#include <string>
#include <utility>
using std::cout;
using std::string;
void move(const string &s) {
cout << "moving " << s << '\n';
}
int main() {
cout << __cplusplus << '\n';
move("umbrella");
}
201103
moving umbrella
Selective using, C++ 17
#include <iostream>
#include <string>
#include <utility>
using std::cout, std::string;
void move(const string &s) {
cout << "moving " << s << '\n';
}
int main() {
cout << __cplusplus << '\n';
move("umbrella");
}
201703
moving umbrella
Starting in C++ 2017, the selective using declarations can be combined.
☼️ ☂️ ⛅️ ☁️ ☔️
Do you carry an umbrella every day, or only when the
weather report predicts rain?
If you carry an umbrella every day, then you’re always dry,
but you have the bother of carrying an umbrella all the time.
If you only carry it when rain is predicted, then you’ll get wet
once in a while. However, you don’t have to lug around an umbrella
when you don’t need it.
It’s a trade-off. Which price do you want to pay? Constant carrying,
or occasional moisture? Both have a cost.
Trade-offs
std::cout << std::setw(5)
<< std::setfill('*')
<< std::hex
<< 42
<< std::endl;
***2a
Similarly …
- Without any using at all, you pay the price of your code
being littered with
std::
prefixes.
#include <iostream>
using std::cin,
std::cout,
std::getline;
- With selective using declarations, you have to keep adding
them as you change your code. They’re all at the top of the file,
so they don’t get in the way of reading the real code.
using namespace std;
Trade-offs
Your choice! My opinions:
std::cout << x << std::endl
makes the code difficult
to read. It’s hard to get past the litter of std::
to see the real code. Perhaps you get used to it.
Prof. Bruce Draper
- Prof. Draper favors using std::cin
(as opposed to using std::cin; see the difference?)
and he’s one of the two finest C++ programmers in the CS Department,
so there’s a lot to be said for that.
- I throw caution to the winds with
using namespace std
.
- I haven’t had a problem … yet.