Alex Rivera | Logout

Why should you prefer unnamed namespaces over static functions?

Asked 2008-09-30T19:02:00.437
715

A feature of C++ is the ability to create unnamed (anonymous) namespaces, like so:

namespace {
    int cannotAccessOutsideThisFile() { ... }
} // namespace

You would think that such a feature would be useless -- since you can't specify the name of the namespace, it's impossible to access anything within it from outside. But these unnamed namespaces are accessible within the file they're created in, as if you had an implicit using-clause to them.

My question is, why or when would this be preferable to using static functions? Or are they essentially two ways of doing the exact same thing?

Edit
Report

1 Answer

46

There is one edge case where static has a surprising effect(at least it was to me). The C++03 Standard states in 14.6.4.2/1:

For a function call that depends on a template parameter, if the function name is an unqualified-id but not a template-id, the candidate functions are found using the usual lookup rules (3.4.1, 3.4.2) except that:

  • For the part of the lookup using unqualified name lookup (3.4.1), only function declarations with external linkage from the template definition context are found.
  • For the part of the lookup using associated namespaces (3.4.2), only function declarations with external linkage found in either the template definition context or the template instantiation context are found.

...

The below code will call foo(void*) and not foo(S const &) as you might expect.

template <typename T>
int b1 (T const & t)
{
  foo(t);
}

namespace NS
{
  namespace
  {
    struct S
    {
    public:
      operator void * () const;
    };

    void foo (void*);
    static void foo (S const &);   // Not considered 14.6.4.2(b1)
  }

}

void b2()
{
  NS::S s;
  b1 (s);
}

In itself this is probably not that big a deal, but it does highlight that for a fully compliant C++ compiler (i.e. one with support for export) the static keyword will still have functionality that is not available in any other way.

// bar.h
export template <typename T>
int b1 (T const & t);

// bar.cc
#include "bar.h"
template <typename T>
int b1 (T const & t)
{
  foo(t);
}

// foo.cc
#include "bar.h"
namespace NS
{
  namespace
  {
    struct S
    {
    };

    void foo (S const & s);  // Will be found by different TU 'bar.cc'
  }
}

void b2()
{
  NS::S s;
  b1 (s);
}

The only way to ensure that the function in our unname

answered 2008-10-01T09:15:19.370

Your Answer