Topic: Cnames, again
Author: Christopher Eltschka <celtschk@web.de>
Date: Tue, 30 Jul 2002 18:30:09 GMT Raw View
Dietmar Kuehl <dietmar_kuehl@phaidros.com> writes:
[...]
> I plug it here anyway: often the C++ headers include the ".h forms" and
> make the names available in namespace 'std', eg.:
>
> // <cstdio>
> #if !defined(__CSTDIO__)
> #define __CSTDIO__
> extern "C" {
> #include <stdio.h>
> }
> namespace std {
> using ::printf;
> // ...
> }
> #endif
>
> Unless the implementation also provides the C library which correctly
> defines the names in namespace 'std', this is only viable approach because
> the C library headers often include system specific names. It is not exactly
> what the standard says, however: the names are defined in the global
> namespace while the standard specifies that they are defined in namespace
> 'std'. This difference matters when it comes to argument dependent name
> lookup because in this case only the namespace where the entities are
> defined is searched. I'm not sure whether the standard C++ library contains
> enough features to somehow tell the difference: To do so, it would be
> necessary to find a function from the standard C++ library (including the C
> functions) using some C types. I'm not sure whether this is possible.
Should be easy to detect the difference, without too much help of the
standard library itself:
#include <ctime>
#include <algorithm>
std::tm x, y;
int main()
{
swap(x,y);
}
For a correcly implemented C++ standard library, struct tm is defined
in namespace std, therefore Koenig lookup should find sort.
For <time.h> directly taken from the C library, this program will not
compile, because there's no swap function in the global namespace.
[...]
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: "mackrune" <rune420_removethis_@start.no>
Date: Tue, 2 Jul 2002 22:35:59 GMT Raw View
I think most implementations do this:
// in cstdio
namespace std {
#include <stdio.h>
}
// in stdio.h
#ifndef STDIO_H // whatever
#define STDIO_H
// ...
#endif
And that would cause the following
#include <cstdio>
#include <stdio.h>
to not place any of stdio's functions in global namespace (only std),
whereas
#include <stdio.h>
#include <cstdio>
would do the opposite. I guess this is undefined behiavor though, so it
might vary.
mackrune
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Dietmar Kuehl <dietmar_kuehl@phaidros.com>
Date: Wed, 3 Jul 2002 19:25:01 CST Raw View
mackrune wrote:
> I think most implementations do this:
>
> // in cstdio
> namespace std {
> #include <stdio.h>
> }
>
> // in stdio.h
> #ifndef STDIO_H // whatever
> #define STDIO_H
> // ...
> #endif
All implementations doing this are wrong! The standard is quite explict
about the meaning of the headers. I think the only non-obvious issue is
whether
#include <cstdio>
int main() { printf("note: no 'std'\n"); }
has to cause a diagnostic from the C++ implementation and the definite
answer is "no" (because <cstdio> is free to include <stdio.h> which in
turn is required to make the names available at global scope). That is,
the program is non-portable but a compiler can legally compile it. From
a user's point of view, the above program is a bad idea.
> And that would cause the following
>
> #include <cstdio>
> #include <stdio.h>
>
> to not place any of stdio's functions in global namespace (only std),
... which would be non-conforming (including <stdio.h> is required to make
the names available at global scope)
> whereas
>
> #include <stdio.h>
> #include <cstdio>
>
> would do the opposite.
... which would also be non-conforming (because <cstdio> is supposed to
actually *define* the names in namespace 'std', not only make them
available and, of course, it is not at all allowed to not make them
available in 'std' at all).
> I guess this is undefined behiavor though, so it might vary.
Nope. This is not undefined.
--
<mailto:dietmar_kuehl@yahoo.com> <http://www.dietmar-kuehl.de/>
Phaidros eaSE - Easy Software Engineering: <http://www.phaidros.com/>
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Dietmar Kuehl <dietmar_kuehl@phaidros.com>
Date: Tue, 2 Jul 2002 03:51:42 GMT Raw View
Greg Comeau wrote:
> I've seen conflicting information from persons about this
> over the years, and so would be interested to see comments
> describing the following C++ programs from persons who really
> feel that they know the answer:
Essentially, you ask which headers put the C functions into namespace std
and possibly make names from this namepace available at global scope. The
rules for this are pretty simple:
- lib.headers paragraph 4: "... In the C++ Standard Library, however, the
declarations and definitions (except for names which are defined as macros
in C) are within namespace scope (basic.scope.namespace) of the namespace
std. ..." This effectively means that any non-macro name in C is defined
namespace 'std' in C++. Whether it is also made available in the global
namespace depends on the implementation and/or on other headers being
included (due to the other points noted).
- lib.using.headers: "A translation unit may include library headers in any
order (clause lex). Each may be included more than once, with no effect
different from being included exactly once, except that the effect of
including either <cassert> or <assert.h> depends each time on the
lexically current definition of NDEBUG."
- lib.res.on.headers paragraph 1: "A C++ header may include other C++
headers." This effectively allows inclusion of the ".h-forms" of the
standard C library headers which in turn make the names available at
global scope, too.
- depr.c.headers paragraph 2: "Each C header, whose name has the form name
.h, behaves as if each name placed in the Standard library namespace by
the corresponding cname header is also placed within the namespace scope
of the namespace std and is followed by an explicit using-declaration
(namespace.udecl)"
I think these are the only rules needed to resolve the examples:
> // 1.cpp
> #include <stdio.h> // AA
>
> int main()
> {
> printf("hi\n"); // BB
> std::printf("hi\n"); // CC
> }
Well-formed.
> // 2.cpp
> #include <cstdio> // DD
>
> int main()
> {
> printf("hi\n"); // EE
> std::printf("hi\n"); // FF
> }
It is permissable for the implementation to compile this witout any
diagnostic but it is not well-formed: It is unspecified whether 'printf()'
is made available in the global namespace.
> // 3.cpp
> #include <stdio.h> // GG
> #include <cstdio> // HH
>
> int main() { }
Well-formed.
> // 4.cpp
> #include <cstdio> // II
> #include <stdio.h> // JJ
>
> int main() { }
Well-formed.
> Are they all "ok"?
Depends on your perspective: From the point of view taken by a C++
implementer they are. From the point of view taken by a C++ user they are
not: The second program is non-portable because there is no guarantee that
'printf()' is made available in the global namespace. However, the
implementation is allowed to make it available.
> I'm less interested in implementation techniques, or common
> perhaps "relaxed" practice, than what the standard (INCLUDING DRs,
> even if will be for TC2) dis/allows.
I plug it here anyway: often the C++ headers include the ".h forms" and
make the names available in namespace 'std', eg.:
// <cstdio>
#if !defined(__CSTDIO__)
#define __CSTDIO__
extern "C" {
#include <stdio.h>
}
namespace std {
using ::printf;
// ...
}
#endif
Unless the implementation also provides the C library which correctly
defines the names in namespace 'std', this is only viable approach because
the C library headers often include system specific names. It is not exactly
what the standard says, however: the names are defined in the global
namespace while the standard specifies that they are defined in namespace
'std'. This difference matters when it comes to argument dependent name
lookup because in this case only the namespace where the entities are
defined is searched. I'm not sure whether the standard C++ library contains
enough features to somehow tell the difference: To do so, it would be
necessary to find a function from the standard C++ library (including the C
functions) using some C types. I'm not sure whether this is possible.
> Greg Comeau 4.3.0 NEWS: New Windows Backends + 'export' IN JUNE!
^^^^
So your web site is not yet updated to offer this version...? :-)
--
<mailto:dietmar_kuehl@yahoo.com> <http://www.dietmar-kuehl.de/>
Phaidros eaSE - Easy Software Engineering: <http://www.phaidros.com/>
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Michiel.Salters@cmg.nl (Michiel Salters)
Date: Tue, 2 Jul 2002 15:47:27 GMT Raw View
comeau@panix.com (Greg Comeau) wrote in message news:<afnf10$39k$1@panix3.panix.com>...
> I've seen conflicting information from persons about this
> over the years, and so would be interested to see comments
> describing the following C++ programs from persons who really
> feel that they know the answer:
[ mixing <cxxxx> and <xxxx.h> forms ]
Could you be a bit more precise? What is unclear about [17.4.1.2
Headers]
and especially D.5 [Standard C library headers]
"Except as noted in clauses 18 through 27, the contents of each header
cname shall be the same as that of the corresponding header name.h, as
specified in ISO/IEC 9899:1990 Programming Languages C (Clause 7),
or ISO/IEC:1990 Programming Languages C AMENDMENT 1: C Integrity,
(Clause 7), as appropriate, as if by inclusion. In the C++ Standard
Library, however,
the declarations and definitions (except for names which are defined
as
macros in C) are within namespace scope (3.3.5) of the namespace std."
"Each C header, whose name has the form name.h, behaves as if each
name
placed in the Standard library namespace by the corresponding cname
header
is also placed within the namespace scope of the namespace std and is
followed by an explicit using-declaration (7.3.3)"
As I read this, the name.h form in C++ is /not/ identical to the C
form,
instead the C form is inserted by inclusion into std:: and the names
are
made available (in an unspecified namespace, presumably such that
valid C programs remain valid - is there a DR on this that I couldn't
find ? The
example isn't normative ).
However, the (normative) wording in D.5 to me means the behavior of
the
name.h is specified fully in terms of the behavior of the cname form
and matching using-declarations. Since neither the repeated inclusion
of the cname form nor the using-declarations constitute undefined
behavior, the inclusion of the name.h form before or after the cname
form constitutes undefined behavior. In the same way, if all names
used in that translation unit are fully qualified, the meaning of the
program doesn't change if the name.h header is included adjacent to
the
cname form.
Wat is interesting is what hapens with names defined by headers
included
by the cname form. The standard seems ambiguous here: Are the names
from
_that_ header "placed in the Standard library namespace by the ...
cname
header" included", i.e. should the name.h form include the same <cxxx>
headers as its corresponding cname form, or should the name.h form
include the xxx.h headers, and what happens if no such form exists?
E.g. if <cstdio> includes <cstdlib> and <iostream>, what should be
included in <stdio.h>?
Regards,
--
Michiel Salters
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: comeau@panix.com (Greg Comeau)
Date: Mon, 1 Jul 2002 22:09:18 GMT Raw View
I've seen conflicting information from persons about this
over the years, and so would be interested to see comments
describing the following C++ programs from persons who really
feel that they know the answer:
// 1.cpp
#include <stdio.h> // AA
int main()
{
printf("hi\n"); // BB
std::printf("hi\n"); // CC
}
// 2.cpp
#include <cstdio> // DD
int main()
{
printf("hi\n"); // EE
std::printf("hi\n"); // FF
}
// 3.cpp
#include <stdio.h> // GG
#include <cstdio> // HH
int main() { }
// 4.cpp
#include <cstdio> // II
#include <stdio.h> // JJ
int main() { }
Are they all "ok"? Please use whatever words properly
describes them: *-formed *-defined, *-conforming, permissable,
whatever.
I'm less interested in implementation techniques, or common
perhaps "relaxed" practice, than what the standard (INCLUDING DRs,
even if will be for TC2) dis/allows.
--
Greg Comeau 4.3.0 NEWS: New Windows Backends + 'export' IN JUNE!
Comeau C/C++ ONLINE ==> http://www.comeaucomputing.com/tryitout
World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries... Have you tried it?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]