Namespaces


Hiding and Ambiguity

#include <iostream>
#include <math.h>

int main(void)
{
  std::cout << sqrt(25.0) << std::endl;   // calls sqrt in math.h
  std::cout << ::sqrt(25.0) << std::endl; // calls sqrt in math.h
  return 0;
}
Now what happens?
#include <iostream>
#include <math.h>

double sqrt(double x)
{
  return x;
}

int main(void)
{
  std::cout << sqrt(25.0) << std::endl;   // Which one?
  std::cout << ::sqrt(25.0) << std::endl; // Which one?
  return 0;
}
The new sqrt function hides the one from math.h and prevents us from using it now. Note that Microsoft and GNU handle this correctly, but Borland's compiler issues an error for both lines:
Ambiguity between 'std::sqrt(double)' and 'sqrt(double)' in function main()
To "unhide" the function, we can "wrap" our new global:
#include <iostream>
#include <math.h>

namespace MyMathFunctions
{
  double sqrt(double x)
  {
    return x;
  }
}

int main(void)
{
  std::cout << MyMathFunctions::sqrt(25.0) << std::endl;  // calls MyMathFunctions::sqrt in this file
  std::cout << sqrt(25.0) << std::endl;                   // calls sqrt in math.h
  std::cout << ::sqrt(25.0) << std::endl;                 // calls sqrt in math.h
  return 0;
}
The 3 compilers tested work fine with the above code.

However, all is not well with Microsoft VC++ 6.0 or GNU either. They also seem to have problems with the math library and the std namespace. By using cmath instead of math.h, a compliant compiler should let you write this:

#include <iostream>
#include <cmath>

double sqrt(double x) { return x; };

int main(void)
{
  std::cout << ::sqrt(25.0) << std::endl;    // Global sqrt function defined in this file
  std::cout << sqrt(25.0) << std::endl;      // Global sqrt function defined in this file
  std::cout << std::sqrt(25.0) << std::endl; // sqrt from cmath
  return 0;
}
The output should be (as produced by the Borland compiler):
25 
25
5
However, MS 6.0 gives this error for the third line:
error C2039: 'sqrt' : is not a member of 'std'
and GNU 3.3 compiles without errors but prints this:
25
25
25
A quick test shows that MS 7.1 compiles, but produces the same results as the GNU compiler.

A final attempt:

#include <iostream>
#include <cmath>
using namespace std;

double sqrt(double x) 
{ 
  return x; 
};

int main(void)
{
  cout << sqrt(25.0) << endl;      // sqrt function defined in this file
  cout << ::sqrt(25.0) << endl;    // sqrt function defined in this file
  cout << std::sqrt(25.0) << endl; // sqrt function defined in cmath
  return 0;
}
Results:
Borland (1): Ambiguity between 'std::sqrt(double)' and 'sqrt(double)' in function main()
MS 6.0 (3): 'sqrt' : is not a member of 'std'
GNU, MS 7.1, Intel:  Compiles cleanly, calls sqrt in file for all.

The moral of the story is that you must be aware of the compliancy of your compiler.