-->

When the C++ standard provides C headers bringing

2019-02-17 09:03发布

问题:

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:

  • C++ math.h and stdlib.h: http://ideone.com/pmD4t
  • C math.h and stdlib.h: http://ideone.com/Sflpn
  • C++ cmath and cstdlib: http://ideone.com/yI07m
  • C++ cmath only: http://ideone.com/KrS3W

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++.

回答1:

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).