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 <algorithm>
#include <iostream>
using namespace std;
void blamp(long w, long h, long d) {
cout << "Type-B lamp, volume=" << w*h*d << '\n';
}
void clamp(long w, long h, long d) {
cout << "Type-C lamp, volume=" << w*h*d << '\n';
}
int main() {
blamp(5, 6, 7);
clamp(5, 6, 7);
}
Type-B lamp, volume=210
Type-C lamp, volume=210
Rock-solid code. That’ll work forever!
#include <algorithm>
#include <iostream>
using namespace std;
void blamp(long w, long h, long d) {
cout << "Type-B lamp, volume=" << w*h*d << '\n';
}
void clamp(long w, long h, long d) {
cout << "Type-C lamp, volume=" << w*h*d << '\n';
}
int main() {
blamp(5, 6, 7);
clamp(5, 6, 7);
}
Type-B lamp, volume=210
Only changed -std=c++14
to -std=c++17
, but the output changed! Why?
The function clamp() was introduced in C++17. It’s a better match for a
three int arguments than a function that takes three long arguments.
#include <algorithm>
#include <iostream>
using namespace std;
void blamp(long w, long h, long d) {
cout << "Type-B lamp, volume=" << w*h*d << '\n';
}
void clamp(long w, long h, long d) {
cout << "Type-C lamp, volume=" << w*h*d << '\n';
}
int main() {
blamp(5, 6, 7);
clamp(5, 6, 7);
}
Type-B lamp, volume=210
- C++ 17’s std::clamp() is a better match than our
clamp()
.
- New compiler, different behavior. 😱
Explicit std::
, C++ 14
#include <algorithm>
#include <iostream>
void blamp(long w, long h, long d) {
std::cout << "Type-B lamp, volume=" << w*h*d << '\n';
}
void clamp(long w, long h, long d) {
std::cout << "Type-C lamp, volume=" << w*h*d << '\n';
}
int main() {
blamp(5, 6, 7);
clamp(5, 6, 7);
}
Type-B lamp, volume=210
Type-C lamp, volume=210
- Some avoid using namespace, and sprinkle their code with
std::
.
- It’s not pretty.
Explicit std::
, C++ 17
#include <algorithm>
#include <iostream>
void blamp(long w, long h, long d) {
std::cout << "Type-B lamp, volume=" << w*h*d << '\n';
}
void clamp(long w, long h, long d) {
std::cout << "Type-C lamp, volume=" << w*h*d << '\n';
}
int main() {
blamp(5, 6, 7);
clamp(5, 6, 7);
}
Type-B lamp, volume=210
Type-C lamp, volume=210
Selective using, C++ 14
#include <algorithm>
#include <iostream>
using std::cout;
void blamp(long w, long h, long d) {
cout << "Type-B lamp, volume=" << w*h*d << '\n';
}
void clamp(long w, long h, long d) {
cout << "Type-C lamp, volume=" << w*h*d << '\n';
}
int main() {
blamp(5, 6, 7);
clamp(5, 6, 7);
}
Type-B lamp, volume=210
Type-C lamp, volume=210
- 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++ 17
#include <algorithm>
#include <iostream>
using std::cout;
void blamp(long w, long h, long d) {
cout << "Type-B lamp, volume=" << w*h*d << '\n';
}
void clamp(long w, long h, long d) {
cout << "Type-C lamp, volume=" << w*h*d << '\n';
}
int main() {
blamp(5, 6, 7);
clamp(5, 6, 7);
}
Type-B lamp, volume=210
Type-C lamp, volume=210
☼️ ☂️ ⛅️ ☁️ ☔️
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.