7

A (file-local; .cpp) const-qualified variable declared at namespace-scope has internal linkage and is thus translation unit local. Is there any reason to/effect of still wrapping the constant in an anonymous namespace?

E.g., is there any reason to prefer any of the following two over the other, and if so, why?

// file.cpp
namespace foo {

const int kMyLocalConstant = 42;  // internal linkage

}  // namespace foo

vs

// file.cpp
namespace foo {
namespace {

const int kMyLocalConstant = 42;  // internal linkage

}  // namespace
}  // namespace foo

I'm grateful to get answers for C++03 as well as C++11, if there is any different in-between the two for this context.


Possible duplicates

I have read the excellent answer to

but I don't see it answering my specific question (please correct me if I'm wrong), as the answer focuses on non-const variable identifiers and non-static free functions. My question focuses on file-local namespace-scoped constants, i.e., variable identifiers which already have internal linkage. Maybe there is a more appropriate dupe that I haven't found.

dfrib
  • 70,367
  • 12
  • 127
  • 192

2 Answers2

4

Strongly prefer unnamed namespace.

Why? Because it makes the rule very easy to remember: if I'm creating a variable/function/template that is intended to be local to a translation unit, I put it in an unnamed namespace, unconditionally, and then I don't have to worry about anything again.

It's true that a non-inline variable of non-volatile const-qualified type that is neither explicitly declared extern nor previously declared to have external linkage will also have internal linkage, but are you really going to choose to put your non-const variables in an unnamed namespace, but const ones outside of one? This would be error-prone if you accidentally forget the const:

// some_tu.cpp
namespace foo {
    int oops = 42;
}

And would you ever mix and match? That's weird:

// some_other_tu.cpp
namespace foo {
    const int a = 0;
    namespace {
        int b;
    }
}

Unnamed namespaces are free - the only cost is the characters it takes to type it. And it means nobody has to stare at this code and have to recall all the subtlety around the [basic.link] rules.

Barry
  • 286,269
  • 29
  • 621
  • 977
  • Thanks for this answer Barry. I guess apart from `inline` variables (C++17?), essentially the same quite exhaustive [basic.link] rule also holds for C++03 and C++11? I.e., it was never a trivial exercise to decide the linkage of a namespace scope variable. – dfrib Aug 15 '18 at 14:16
  • 1
    @dfri Yeah, [C++11 wording](https://timsong-cpp.github.io/cppwp/n3337/basic.link#3.2). Added wording about `volatile` at some point too. – Barry Aug 15 '18 at 14:51
  • Is there any risk of collision with names from 3rd-party code `#include`d in this translation unit? If so, is there some small value to confining all project code to the project's namespace? – John McFarlane Aug 06 '23 at 09:21
  • 1
    @JohnMcFarlane I mean, if you get an ambiguous lookup, you can always change something - but is that really a big deal? Do you have a lot of includes that define names in the global namespace that happen to match whatever names you wanted to use for some local variable? – Barry Aug 06 '23 at 17:05
1

The unnamed namespace is redundant, there is no benefit using it in this case.

The only case I'd put a const into an unnamed namespace is when there's other stuff (functions, etc.), which should have internal linkage too, and the const and the other stuff are coherent.

geza
  • 28,403
  • 6
  • 61
  • 135