R. Clayton (rclayton@monmouth.edu)
(no date)
During the discussion of include files that opened up the std namespace, a
question came up about dealing with those kinds of include files.
$ cat unruly.h
#ifndef UNRULY_H
#define UNRULY_H
#include <vector>
using namespace std;
#endif
$ cat t.cc
#include "unruly.h"
typedef int * vector;
int main() {
vector i = new int [10];
}
$ g++ -c t.cc
t.cc: In function `int main()':
t.cc:6: `vector' undeclared (first use this function)
t.cc:6: syntax error before `=' token
$ CC -c t.cc
"t.cc", line 6: Error: The name vector is ambiguous,
vector and std::vector<std::T, std::Allocator>.
1 Error(s) detected.
$
(Notice, by the way, the quality of error messages produced by g++ and CC.)
I mentioned that one solution would be to enclose the include file in a scope
so the name-space pollution doesn't spread too far. I also mentioned I did
this for the SaferSTL to print error messages. Here's an example:
void _M_range_check(size_type __n) const {
const size_type vs = size_type(this->_M_finish-this->_M_start);
if (__n >= vs) {
# include <cstdio>
fprintf(stderr,
"Accessing element %u in a vector containing %u element%s.\n",
__n, vs, __n == 1 ? "" : "s");
abort();
}
}
To show that the namespace was being contained, I also cooked up example
int main(int argc) {
if (argc) {
# include <cstdio>
}
else
fprintf(stderr, "hello world!");
}
which shouldn't compile because fprintf() is undefined in the else branch.
Alas, this example didn't compile, but for the wrong reason:
$ g++ -c t.cc
In file included from
/usr/local2/lib/gcc-lib/../../include/c++/3.2.3/cstdio:50, from t.cc:3:
/usr/local2/lib/gcc-lib/../../include/c++/3.2.3/cstddef:
In function `int main(int)':
/usr/local2/lib/gcc-lib/../../include/c++/3.2.3/cstddef:51:
syntax error before `{' token
/usr/local2/lib/gcc-lib/../../include/c++/3.2.3/cstddef:53:
`size_t' not declared
[ much blah blah blah deleted ]
$
On further investigation, it turns out that namespaces (among other things)
have to be declared at global scope. Because <cstdio> contains namespaces
definitions, the two functions above won't compile because <cstdio> tries to
define namespaces in non-global scope.
It is still possible to tame an unruly include file using scopes, but the
restriction to global scopes makes the technique clumsier and less useful. It
also requires that the unruly include file not contain any declarations that
must be at global scope (which, for all intents and purposes, means that scope
restriction is useless: any include file that opens namespaces is almost
certainly going to contain namespace declarations, which must be at global
scope). The easiest way to handle this problem is to not write include files
that open namespaces into global scope.
I'll leave you with an interesting question: how come _M_range_check() compiles
but main() doesn't? (There are several answers to this question, but one is
most likely correct.)
This archive was generated by hypermail 2.0b3 on Mon May 03 2004 - 17:00:06 EDT