CS253: Software Development with C++

Fall 2021

Symbol Ambiguity

Show Lecture.SymbolAmbiguity as a slide show.

CS253 Symbol Ambiguity

or

“Them there namespacies is trickier then I done thought!”

The __cplusplus symbol

% 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

What version do we use?

It’s easy to tell which version of the standard is in use:

cout << __cplusplus / 100;
2017

using namespace, C++ 98

#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

using namespace, C++ 11

#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 &).

using namespace, C++ 11

#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

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

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

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 …

#include <iostream>
using std::cin,
      std::cout,
      std::getline;
using namespace std;

Trade-offs

Your choice! My opinions:

a picture of Prof. Bruce Draper
Prof. Bruce Draper