3

I've heard it asserted that the use of unnamed namespaces in C++ to define functions and ensure that they cannot be called from outside the compilation unit in which they are defined is not good in very large code environments because they cause the symbol table to grow unnecessarily large by including entries to these symbols in the automatically generated namespaces that the C++ compiler provides when unnamed.

namespace {
  // This function can only be accessed from hear to the end of 
  // any compilation unit that includes it.
  void functionPerhapsInsertedIntoSymbolTable() {
    return;
  }
}

This is perhaps given that the above is supposed to be the same as doing the following:

namespace randomlyGenerateNameHereNotCollidingWithAnyExistingNames {
  // This function can only be accessed from hear to the end of
  // any compilation unit that includes it.
  void functionPerhapsInsertedIntoSymbolTable() {
    return;
  }
}
using randomlyGenerateNameHereNotCollidingWithAnyExistingNames;

However, is it really that simple, is the compiler required to make a symbol table entry for symbols in the generated namespace name?

Instead, in such situations, I heard it suggested to use a static declaration:

// This function can only be accessed from hear to the end of
// any compilation unit that includes it.
static void functionNotInsertedIntoSymbolTable() {
  return;
}

Is it true that using a static declaration before a function instead of placing it in an unnamed namespace has the same effect of making the function inaccessible outside the compilation unit in which it is defined? Is there any difference between these two approaches other than potentially not causing the symbol table to grow?

Is the issue with symbol table bloat due to unnamed namespaces just a bug in some implementations of C++ or is the compiler somehow required by the standard to create entries for such functions? If this bloat is considered a bug, are there known compilers for which this is not an issue?

WilliamKF
  • 41,123
  • 68
  • 193
  • 295
  • 1
    You can also probably reduce symbol table size by only using names like `f(x)` and `g(y)`, but that is not a good idea either. – Bo Persson Jan 17 '13 at 18:26
  • Do you have any evidence to support the assertion that unnamed namespaces bloat symbol tables? – Pete Becker Jan 17 '13 at 18:50
  • It is claimed by other developers in the company, I have no direct experience myself. We are not on C++11 yet. – WilliamKF Jan 17 '13 at 18:51
  • 1
    Why the downvote(s)? If it is true, it would be good to know if static methods prevent the problem. If it is false, then it would be good to have a solid answer we can use as a reference... – André Jan 17 '13 at 18:52

2 Answers2

4

Is it true that using a static declaration before a function instead of placing it in an unnamed namespace has the same effect of making the function inaccessible outside the compilation unit in which it is defined?

Yes.

Namespace-static was deprecated in C++03 in favour of unnamed namespaces, but in fact un-deprecated for C++11 when everybody realised that they are just the same thing and there was no purpose to the deprecation.

Is there any difference between these two approaches

No, not really. There may be some minor subtleties with name lookup due to the use of a namespace, but I can't think of any right now.

other than potentially not causing the symbol table to grow?

Since this is a language-lawyer question with no evident practical problem to solve, I am obliged to point out that the C++ language has no concept of a symbol table, and thus no indication of this effect.

It's also not going to have any noticeable effect until you have tens of thousands of unnamed namespaces; do you?

Community
  • 1
  • 1
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
0

The reason for the unnamed namespace and deprecation of namespace level static is the ill-fated export keyword.

Everything an exported template relies on has to be link-accessible at the points of instantiation, which are most likely in different source files. The unnamed namespace allowed the 'privatization' aspect of static while still preserving linkage for exported templates.

Now that export has been removed in C++2011, I'm pretty sure the external linkage requirement for the unnamed namespace has been removed, and it now behaves exactly like namespace level static. Someone more familiar with the standard can confirm/refute this.

Ryan Witmer
  • 331
  • 2
  • 8
  • `[C++11 3.5/4]` gives unnamed namespaces internal linkage; I can find no evidence thus far that this was not the case in C++03, though the wording is much more complex. – Lightness Races in Orbit Jan 17 '13 at 19:20
  • `[C++03 3.5/4]` does seem to imply that names _within_ namespaces have external linkage except in a bunch of cases which do not include being in an unnamed namespace, unless the name itself is of a namespace. – Lightness Races in Orbit Jan 17 '13 at 19:22