6

The final committee draft of the upcoming C++0x standard says:

Every C header, each of which has a name of the form name.h, behaves as if each name placed in the standard library namespace by the corresponding cname header is placed within the global namespace scope. It is unspecified whether these names are first declared or defined within namespace scope (3.3.6) of the namespace std and are then injected into the global namespace scope by explicit using-declarations (7.3.3).

Earlier C++ standards read similarly.

My question is, when the C++ header #include<cname> uses overloaded functions, are all overloads brought in by #include<name.h>, since overloads aren't separate "names"?

And should the behavior of the following code differ between standard-compliant C and C++ compilers?

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int main(void)
{
    double arg = -2.5;
    double result = abs(arg) / 3;
    printf("%f\n", result);
    return 0;
}

Compile-ready test cases:

From this test, C++ math.h acts like C and not like C++ cmath.

But on Visual C++ 2010, C++ math.h acts like C++ cmath.

And a compile-time canary for use with Comeau try-it-out:

#include<stdio.h>
#include<stdlib.h>
#include<math.h>

template<typename T> struct typecheck {};
template<> struct typecheck<int> { enum { value = 1 }; };

template<typename T>
typecheck<T> f(const T& t) { return typecheck<T>(); }

int main(void)
{
    double arg = -2.5;
    auto result = abs(arg) / 3;
    printf("%d\n", f(result).value);
    return 0;
}

Result:

Comeau C/C++ 4.3.10.1 (Oct  6 2008 11:28:09) for ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing.  All rights reserved.
MODE:strict errors C++ C++0x_extensions

"ComeauTest.c", line 15: error: class "typecheck<double>" has no member "value"
      printf("%d\n", f(result).value);
                               ^

1 error detected in the compilation of "ComeauTest.c".

Comeau agrees with Visual C++.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • I didn't know Comeau supported `auto`. That is very useful to know. I think you can also test it simply by not including ``. `` should only include `abs` in C++, not in C. – James McNellis Dec 10 '10 at 06:14
  • @James: I assume you meant `stdlib.h` and not `stdio.h`. I ran into that while developing the example, on ideone (gcc-4.3.4) the C++ version with `math.h` only would not compile. – Ben Voigt Dec 10 '10 at 14:33
  • Agh. Yes. I meant ``. – James McNellis Dec 10 '10 at 16:12

1 Answers1

3

Yes, all overloads should be brought into the global namespace. My understanding is that the math.h header is intended to look something like:

// math.h:
#include <cmath>

using std::abs;
// etc.

So, yes: the behavior of your example program is different when compiled as a C program than when compiled as a C++ program. As a C++ program, it will call std::abs(double) from <math.h>. As a C program it will call abs(int) from <stdlib.h> (this is the only abs function in the C Standard Library, since C does not support function overloading).

James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • But `abs` in C doesn't accept a `double` argument, so you're really saying the behavior would differ? – Ben Voigt Dec 10 '10 at 05:19
  • @Ben: My apologies; I totally misread your question. Yes, the behavior would differ. – James McNellis Dec 10 '10 at 05:23
  • @James: So it's a bug in gcc then? – Ben Voigt Dec 10 '10 at 05:41
  • @Ben I didn't read the question very carefully, but I would trust Comeau for adherence to the C++ Standard before any other compiler. – Karl Knechtel Dec 10 '10 at 05:57
  • @Karl: So do I, that's why I worked out a compile-time test, because the free online comeau only compiles, no chance to link or execute. The question really has become not whether bringing in the overloads is allowed (Comeau does, so surely it as allowed), but whether it's required. – Ben Voigt Dec 10 '10 at 06:05
  • My guess is that, yes, gcc is wrong. However, this is an area where many implementations are not conforming. One problem is that many platforms use the actual C Standard Library headers directly, in which case you can't get the behavior specified by the paragraph you cite. Also, you can't get the correct behavior from the cname headers because they end up having to include the name.h headers an put `using ::name` in a `namespace std { }` block, so the names end up both in the std namespace and in the global namespace. There have been some changes to the standard in C++0x for this, though I – James McNellis Dec 10 '10 at 06:10
  • am not entirely sure what those changes were and I don't have Acrobat installed on this new laptop to find out just now :( – James McNellis Dec 10 '10 at 06:10
  • @James: The next paragraph following the one I cited is a relevant note: [ Example: The header assuredly provides its declarations and definitions within the namespace std. It may also provide these names within the global namespace. The header assuredly provides the same declarations and definitions within the global namespace, much as in the C Standard. It may also provide these names within the namespace std. — end example ] – Ben Voigt Dec 10 '10 at 06:20
  • @James: BTW, I've started to prefer "PDF-XChange Viewer" for all my pdf viewing needs (assuming a Windows platform), it starts much faster, uses less memory, and doesn't hang my browser the way Acrobat Reader does. – Ben Voigt Dec 10 '10 at 06:21
  • @James hm, my understanding was that the "cname" versions do add things to the "name.h" versions. The quoted part to the standard requires (instead of just accepting) the name.h versions to also have those additional overloads and such. That sounds weird to me. – Johannes Schaub - litb Dec 10 '10 at 06:21
  • @Ben: I think that is new in C++0x. I've been using Foxit recently for PDF reading, but I'll check out PDF-XChange; thanks for the recommendation. – James McNellis Dec 10 '10 at 06:21
  • @James: `[headers]` from FCD: Except as noted in Clauses 18 through 30 and Annex D, the contents of each header cname shall be the same as that of the corresponding header name.h, as specified in the C standard library or the C Unicode TR, as appropriate, as if by inclusion. In the C ++ standard library, however, the declarations (except for names which are defined as macros in C) are within namespace scope of the namespace std. It is unspecified whether these names are first declared within the global namespace scope and are then injected into namespace std by explicit using-declarations. – Ben Voigt Dec 10 '10 at 06:25
  • I think I have been wrong though. The wording seems to clearly require the name.h versions to contain C++ overloads. – Johannes Schaub - litb Dec 10 '10 at 06:25
  • @Johannes: I'm thinking about this as well. As stated in the quote cited in the OP, you can't use an actual C Standard Library headers in a C++ Standard Library implementation; you have to have a separate set of headers with the C++ overloads in them. I had thought that it was intended that you could use the C Standard Library headers directly, but I may have been wrong. LWG Defect 456 is the only defect I know of concerning this, and it doesn't discuss this particular aspect of the issue. – James McNellis Dec 10 '10 at 06:27
  • @Ben: That language is new in C++0x; it was modified by the resolution to [LWG Defect 456](http://www.comeaucomputing.com/iso/lwg-defects.html#456). – James McNellis Dec 10 '10 at 06:29