1

I have two header files that I'm including from my main.cpp that have the following definition in an anonymous namespace: const string strToken = ("%"); Compiling using g++ version 4.9 results in this:

In file included from main.cpp:25:0:
libraries/trace.h:31:14: error: redefinition of ‘const string {anonymous}::strToken’
 const string strToken = ("%");
              ^
In file included from libraries/debuglogger.h:12:0,
                 from libraries/packet.h:10,
                 from main.cpp:20:
libraries/strformat.h:23:14: note: ‘const string {anonymous}::strToken’ previously declared here
 const string strToken = ("%");
              ^

I had thought that putting something in an anonymous namespace limited it to file scope, making this a non-issue. Am I missing something, or is this some sort of defect in GCC? If anyone wants the full code I would be willing to include it, but I'm hoping I've included enough information in my question to not need it.

IanM
  • 109
  • 9
  • Why do you have an anonymous namespace in a header file? There will be a copy of "%" in memory for every include. – Neil Kirk Feb 01 '15 at 01:49
  • @NeilKirk So I'm going to take a step back here. Lets say I don't want to limit access to this string to my header file. How can I do that without making it a private member of the class or using an anonymous namespace? – IanM Feb 01 '15 at 01:51
  • I'm not sure from your posts if you want to hide it from the including files or make it available. – Neil Kirk Feb 01 '15 at 02:11
  • @NeilKirk I would like it hidden from the including files. – IanM Feb 01 '15 at 02:16
  • Ideally it would be defined only in the source file associated with this header file, unless you have template code or inline functions or a default parameter relies on it. – Neil Kirk Feb 01 '15 at 02:18
  • @NeilKirk Ah, I suppose that was an important detail I left out: I do have template code in these headers. – IanM Feb 01 '15 at 02:39

2 Answers2

3

I had thought that putting something in an anonymous namespace limited it to file scope

You were just a bit off. Putting things in an anonymous namespace limits their visibility to the translation unit they appear in. A translation unit is everything that turns into a single object file, which is typically one source file (.cpp file) along with all the code from the header files that are included from that source file. So, when you have main.cpp which includes two headers that have the same declarations (in an anonymous namespace or not), you get an error.

Always think about the #include statements as being essentially just a copy-paste of the content of the header in place of the include statement. These kinds of issues become a lot easier to deal with once you understand that. For example, your particular case basically boils down to having this code after the include-statement have been resolved (copy-pasted into the source file):

// from first header:
namespace {
  const string strToken = ("%");
};

// from second header:
namespace {
  const string strToken = ("%");
};

int main() { ... };

where the error is pretty obvious, and anonymous namespace really won't change anything to the basic problem that you have multiple definitions of the same thing.

Anonymous namespaces are mainly there so that you can create things inside a translation unit (usually in the .cpp file itself) without having any traces of them appearing after compilation of the translation unit into an object file. You might find this tutorial helpful in understanding the whole compilation and linking process.

Mikael Persson
  • 16,908
  • 6
  • 34
  • 49
1

I've discovered after doing some research that anonymous namespaces in headers are a bad idea. See here for possible solutions: Hiding a C++ class in a header without using the unnamed namespace

Community
  • 1
  • 1
IanM
  • 109
  • 9