7

I have a fairly large application and I am working without the std namespace, I noticed I wasn't including std::cos or std::sin yet I am getting the right results. Why?

An example of some cut down code would be:

#include <ctime>
#include <cmath>
#include <iostream>
#include <vector>
//#include <unistd.h>
#include <fstream>
#include <sstream>
#include <iomanip>

using std::cout;
using std::endl;

int main()
{
    double pi = 4*(atan(1));

    cout << "pi = " << pi << endl
         << "cos(pi) = " << cos(pi) << endl
         << "sin(pi) = " << sin(pi) << endl;



    return 0;
}

I have left all the headers in, I am using them all in the main code. The output returns ~3.14, -1 and 1e-16 as expected. Why does this work? cos and sin are in std aren't they?

I'm using the g++ compiler on a remote unix server

Thanks

Aaron
  • 7,015
  • 2
  • 13
  • 22
  • 3
    Does Mike Seymour's answer help you? http://stackoverflow.com/questions/11085916/why-are-some-functions-in-cmath-not-in-the-std-namespace – bblincoe Jan 03 '14 at 12:10

2 Answers2

9

When you include <cmath>, all of the functions are declared in std::. For the C headers, there is also a special rule, which allows (but doesn't require) the implementation to make them visible in the global namespace; this is because most implementations will simply adapt the C headers, something like:

#include <math.h>
namespace std
{
    using ::sin;
    using ::cos;
    // ...
}

This is an obvious way of implementing the library without having to rewrite everything, just to have it in C++, and it will result in all of the names also being present in the global namespace.

Formally, this is a C++11 feature; pre-C++11 required that <cmath> only introduce the symbols into std::. Practically, all, or at least most implementations did something like the above, and did introduce them, illegally, into the global namespace, so C++11 changed the standard to reflect reality.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
7

Unfortunately, library implementations are allowed to dump names from the C library into the global namespace as well as std, and many do. Even worse, in some cases only some overloads are available in the global namespace, leading to unexpected loss of precision if you don't specify the std version.

You should always use the std versions, but sadly there's no reliable way to enforce that, so you'll just have to tread carefully through this particular minefield.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • The fact that in some cases, only some overloads are available is a good point (that I'd forgotten, although I've been bit by it). – James Kanze Jan 03 '14 at 12:14