Search code examples
c++namespaceslanguage-lawyerstandards-compliance

pollution of global namespace by standard header files


Time and again I run into problems from namespace pollution due to indirect inclusion of C-header files from C++ standard headers. For example, on my linux system gcc's (version 5.1.1) <thread> includes usr/include/bits/sched.h, which declares

extern "C" {
  extern int clone(int (*__fn) (void *__arg), void *__child_stack, int __flags, void *__arg, ...) throw();
}

In the following minimal example

#include <thread>                              // indirect inclusion of <sched.h>

namespace {
  struct foo
  { virtual foo*clone() const=0; };

  foo*clone(std::unique_ptr<foo> const&);      // function intended

  struct bar : foo
  {
    std::unique_ptr<foo> daughter;
    bar(foo*d) : daughter(d) {}
    foo*clone() const
    { return new bar(::clone(daughter)); }     // to be called here
  };
}

the compiler complains about the call to ::clone() not matching the definition from bits/sched.h (ignoring the definition just before). (Note that simply calling clone instead of ::clone clashes with the member.)

So, the questions are:

  1. Is gcc correct to discard my version of clone() when trying to resolve the function call ::clone(daughter)?
  2. Is the pollution of the global namespace in this way standard compliant?
  3. In the above example, can I resolve the problem without renaming my clone() functions (or the anonymous namespace) but still including <thread>?

Solution

    1. Is gcc correct to discard my version of clone() when trying to resolve the function call ::clone(daughter)?

    Yes, I think so.

    1. Is the pollution of the global namespace in this way standard compliant?

    It's arguable. For a pure C++ implementation, no, but there aren't many of them. In practice most are "C++ on POSIX" or "C++ on Windows" implementations and declare lots of names that are not in the C++ standard.

    The namespace pollution problem is well known (11196, 51749 and others), with no simple solution.

    The problem is that most C++ standard library implementations don't control the C library and just include the platform's native C headers, which pull in other names.

    1. In the above example, can I resolve the problem without renaming my clone() functions (or the anonymous namespace) but still including ?

    In your specific case you can solve the name lookup problem by putting your clone overload in the global namespace so lookup finds it at the same time as the function in <sched.h> and by making it static to give it internal linkage again.