A document is valid if all the tags contained within the document are matched. It is certainly true that, given a document with no tags, all the tags within the document are matched because there are no tags. Because all tags within the document are matched, the document is valid.
If you don't like the reasoning in the previous paragraph, then try this: if a document with no tags is not valid, then you should be able to point to some tags within the document that are mismatched. In the absence of specific tags that are mismatched, it's hard to argue that the document is not valid.
int main() { # include <cstdio> // whatever }
doesn't compile: cstdio
tries to manipulate the std
name-space in
main()
's local environment. However, that e-mail also indicated that I
pulled that same trick in SaferSTL with no apparent problems; for example the
code
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 %u-element vector.\n", __n, vs); abort(); } }
compiled with no error. How do you explain this behavior?
Hint: this question can be answered entirely from the contents of the lecture about include files; it is not necessary to involve any other aspect of C++.
The main()()
example tells us that including the contents of cstdio
in
a local scope causes compilation errors. The _M_range_check()
example,
because it compiles, tells us that the contents of cstdio
must not have
been included within the _M_range_check()
's local scope because if it had,
the function wouldn't have compiled.
We now have to figure out why the contents of cstdio
weren't included in
_M_range_check()
's local scope. Recalling the include-file lecture, include
files can use the #ifndef
idiom to prevent, among other problems,
duplicate definitions, and this gives us the answer: cstdio
was included
earlier in the same .h file that contains _M_range_check()
. The earlier
inclusion prevented any later inclusions, the _M_range_check()
include among
them.
typea a = "hello "; typeb b = "!"; std::string c = a + "world" + b;
compiles successfully if +
is left-associative but results in a type error
if +
is right-associative. What are the types of a
and b
?
Explain your answer.
According to Koenig and Moo (page 4), a left-associative operator takes a big a
left operand as it can; that is, parentheses are added from the left. If
+
is left associative, then
std::string c = a + "world" + b;
is parenthesized as
std::string c = (a + "world") + b;
From this we know that a
can't be of type char *
because +
isn't
defined for two pointer operands. type
a is std::string
, as is
the a + "world"
subexpression. However, b
could be either a string
or a character pointer.
If +
is right associative, then
std::string c = a + "world" + b;
is parenthesized as
std::string c = a + ("world" + b);
Because this expression doesn't compile, it must be the b
is of type
char *
.
"Free form" means that space characters in excess of those needed to separate program parts are irrelevant and are ignored; in addition, when not ignored, one space character is the same as any other space character.
String literals are not free form for two reasons. First, Excess space
characters are significant in string literals; the strings "a b"
and
"a b"
are different. Second, the differences between space characters
are significant within string literals; the string
"a b"
is different from the string literal
"a b"
which is not a string literal at all.
This page last modified on 2 February 2004.