2

test.cpp

#include "test.hpp"

void f1() { }

namespace {
   void f2() {}
}

namespace test {
   void f3() { }
}

Please correct me if I'm wrong, but:

  • f1 can be called from outside if it is declared in the header file or an extern statement is used
  • f2 can't be called from outside
  • f3 can be called from outside if it is declared in the header file (and properly prefixed - test::). If it is not declared in a header, it can't be called?

Am I right?

Joshua MN
  • 1,486
  • 2
  • 13
  • 26

1 Answers1

3

Your question title is misleading. Don't put an anonymous namespace in a header, ever.

f2 can't be called from outside of test.cpp, correct.

f1 and f3 can be called if appropriate declarations are available. These can be in a header, but nothing stops other .cpp files from simply having the code that would be in a header, even if you don't provide one.

Also, extern is not needed for function declarations.

void f1();
namespace test {
  void f3();
}
Sebastian Redl
  • 69,373
  • 8
  • 123
  • 157
  • *Don't put an anonymous namespace in a header, ever.* - why? – Joshua MN Aug 29 '13 at 16:10
  • 5
    Aside from the functions in there being uselessly duplicated into every cpp file that includes the header, it also creates very subtle issues in some situations, e.g. if you then have an inline function in that header that is not in the anonymous namespace but uses something from the anonymous namespace. There is one situation I know of where doing this is the right thing, but it's extremely rare and subtle, and you won't need it unless you're into writing complex header-only libraries like those in Boost. For 99.99% of the C++ programmers, "never" is the only rule they need. – Sebastian Redl Aug 29 '13 at 16:17
  • 1
    Why shouldn't you *ever* put anonymous (or unnamed) namespace in a header? Boost does exactly that with the `_1`, `_2` etc, `bind` placeholders. All it means is every translation unit ends up with its own copy of whatever's in the namespace. Also, to be pedantic, you *could* call `f2()` from another TU, *if* you could get hold of the compiler generated namespace name. This is because `f2()` does have external linkage. In practice this is impossible because there's no way to get the auto-generated name. (OK, I see you mentioned exceptions for the header thing while I was typing this comment) – Praetorian Aug 29 '13 at 16:20
  • 1
    @Praetorian That's the one situation I was talking about, but note that Boost.Bind's use has been criticized as technically causing undefined behavior when there's an inline function outside an unnamed namespace using the placeholders. That's why I said subtle issues. – Sebastian Redl Aug 29 '13 at 16:23
  • Seems I'm wrong about the [linkage of names within unnamed namespaces](http://stackoverflow.com/questions/10832940/why-do-functions-objects-inside-anonymous-namespace-have-external-linkage), the rules changed in C++11 so that these now have internal linkage. – Praetorian Aug 29 '13 at 16:44
  • Let me just read and analyze all your discussion and references.. Generally thanks a lot! – Joshua MN Aug 29 '13 at 17:12