Show Lecture.ImplicitInclusion as a slide show.
CS253 Implicit Inclusion
Dubious Code
Is this code correct? I mean, sure, it’s factually correct,
but is it a correct C++ program?
#include <iostream>
using namespace std;
int main() {
string s = "Han shot first!\n";
cout << s;
}
Han shot first!
Bad Code
#include <iostream>
using namespace std;
int main() {
string s = "Han shot first!\n";
cout << s;
}
Han shot first!
The code is not correct. A std::string was defined,
but there is no #include <string>. But, still, it compiled. ☺? ☹?
Not a Cause for Celebration
- You may think, “What’s the problem? So it compiles.
That doesn’t bother me. Now, if it ever fails to compile,
let me know.”
- Sure, it compiles, but it doesn’t have to.
- It might stop compiling come the next compiler release.
- It might not compile using another compiler (e.g., clang++ vs. g++).
operator<<
Light Dawns
#include <iostream>
using namespace std;
int main() {
string s = "Han shot first!\n";
cout << s;
}
Han shot first!
- Now, we understand how this can compile.
- It must be that, on this particular compiler, <iostream>
includes <string>.
- Can we count on that? No!
- On another computer, <string> might #include <iostream>.
- Or, <iostream> might conditionally define
operator<<
only if
<string> has already been included, and vice versa.
Solution
#include <iostream>
#include <string>
using namespace std;
int main() {
string s = "Han shot first!\n";
cout << s;
}
Han shot first!
- To write a portable program:
- #include what you need.
- Don’t count on an accident of implementation.
- It’s a shame that the compiler doesn’t tell us that we got it wrong.
- This is why computer programmers get the big bucks.
Theoretical
- Is this just theoretical handwringing? No.
- Compiler vendors are currently quite casual about having
one header file include another.
- It is permitted by the standard.
- For nearly every assignment, somebody turns in code
that compiles on their computer, but fails on CSU computers.
Example
Consider this program, compiled on my Macbook Air under macOS:
% cat c.cc
#include <cmath>
int main() {
return isinf(0.0);
}
% g++ c.cc
% ./a.out
% g++ --version
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 8.0.0 (clang-800.0.42.1)
Target: x86_64-apple-darwin15.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
Example
The same program, compiled on a CSU CS Department computer:
% cat c.cc
#include <cmath>
int main() {
return isinf(0.0);
}
% g++ c.cc
c.cc: In function ‘int main()’:
c.cc:3:12: error: ‘isinf’ was not declared in this scope
return isinf(0.0);
^~~~~
c.cc:3:12: note: suggested alternative:
In file included from c.cc:1:0:
/usr/include/c++/7/cmath:612:5: note: ‘std::isinf’
isinf(_Tp __x)
^~~~~
% g++ --version
g++ (GCC) 7.3.1 20180130 (Red Hat 7.3.1-2)
Conclusion
TEST ON THE TARGET MACHINE