9

I have defined some functions (no classes involved here) in an external *.cpp file, and of course there is an appropriate *.h file.

Some of the functions in the *.cpp file are used only in that *.cpp file nowhere else. They are not even mentioned in the *.h file.

Should I put those functions into an unnamed namespace or may they live just next to the other functions? And if so, why should I need an unnamed namespace for them? I cannot see a problem, since those functions are not accessible from outside anyway.

Cœur
  • 37,241
  • 25
  • 195
  • 267
user1192880
  • 101
  • 1
  • 3
  • Why not just make them `static`? (as in a static C function, not a static class method) – James M Feb 06 '12 at 17:41
  • 1
    @JamesMcLaughlin: Well in C++03 `static` was deprecated for that purpose. However, C++11 un-deprecates it. But `static` and being in the unnamed namespace mean different things. `static` will give it internal linkage, so the function can't be used for some purposes. – Fred Larson Feb 06 '12 at 17:45
  • Thanks for your suggestions. Is any of those solutions, static or unanmed namespace, recommended or preferred? – user1192880 Feb 06 '12 at 17:49
  • 1
    @FredLarson The only reason it was un-deprecated in C++11 was because the committee felt that it wasn't realistic to get people to stop using it, not because they changed their minds about its use. – David Stone Jun 17 '12 at 19:40

3 Answers3

25

If you want them to be truly private to that compilation unit, put them in an anonymous namespace. If you don't then someone could declare those functions elsewhere and use them explicitly.

Take the following example:

// library.cpp

// a "private" function here, in that it is not declared anywhere
void f() {}

namespace
{
   // same as above, except within an anonymous namespace
   void g() {}
}

// client.cpp

void f();

int main()
{
   // Can call f(), it's been declared and is now effectively "public"
   f();

   // compilation error, this has no idea what g() is, it's not declared 
   // in any scope that can be resolved here
   g();

   return 0;
}
Chad
  • 18,706
  • 4
  • 46
  • 63
  • Thank you! I was not aware of that "feature". – user1192880 Feb 06 '12 at 17:50
  • This is what `static` is for. Anonymous namespaces provide this feature for classes and structs. – Clark Gaebel Feb 06 '12 at 18:01
  • Does the `static` keyword also protect against name collision with other functions that may exist in other parts of the code? The unnamed namespace will. – Chad Feb 06 '12 at 19:09
  • How about if I put the declaration of g() + its namespace inside a header file (e.g. library.h) and include it in my client.cpp? Is the fine then? – TonySalimi Aug 01 '19 at 11:09
4

Your question can be split in two:

1. "How can I hide global functions ?"

One simple way to do that, is NOT to put the header of the function into the header file:

//============================
// Filename: "mylibrary.hpp"
//============================
// Description:
// Utility functions.
//============================
#ifndef MYLIBRARY_H_INCLUDED
#define MYLIBRARY_H_INCLUDED
//============================

namespace MyLibrary
{
    void DoSomething();
} // namespace MyLibrary

//============================
#endif // MYLIBRARY_H_INCLUDED
//============================

Full code file:

//============================
// Filename: "mylibrary.cpp"
//============================
// Description:
// Utility functions.
//============================
// self header include
#include "mylibrary.hpp"
//============================

namespace MyLibrary
{
    void DoSomethingBefore()
    {
      // ...
    }

    void DoSomethingAfter()
    {
      // ...
    }

    void DoSomethingConfirmed()
    {
      // ...
    }

    void DoSomething()
    {
      DoSomethingBefore();
      DoSomethingConfirmed();
      DoSomethingAfter();
    }
} // namespace MyLibrary

//============================
#endif // MYLIBRARY_H_INCLUDED
//============================

When this is compiled, you get a "mylibrary.o" or "mylibrary.obj" file. You may provide it, to other developers as: "mylibrary.hpp" plus "mylibrary.obj", but, without the "mylibrary.cpp" file. Most "plain c" / "c++" compilers can work this way.

There are other ways, read the next section.

2. "Are anonymous namespaces, a good technique to hide global functions ?"

The "Anonymous Namespaces" technique, is another way to hide global functions.

There is a similar question on:

Unnamed/anonymous namespaces vs. static functions

But, personally, I don't recommend this technique, as the "favorite" answer.

Namespaces are one of those things, that I wish existed since the start of "pure c" or "c++". But, "anonymous namespaces" or "unnamed namespaces", seems weird to use.

Its like trying to hide something, and, later, forget, where do you store it.

3 Additional suggestions

(a) I suggest to use a single main REQUIRED, not optional, non-anonymous namespace per file. It may have nested, additional inner namespaces. Each main namespace, should have the same id. as the filename, but, without the file extension or file suffix.

(b) Avoid anonymous namespaces. Its like storing things in a warehouse, without an index.

(c) Use a file extension, or file prefix, in your header files, maybe ".h", or ".hpp", even if if its a c++ file. The standard says c++ shouldn't use an file extension or file suffix on "c++" files, but are difficult to identify or find on the filesystem.

Good Luck.

Community
  • 1
  • 1
umlcat
  • 4,091
  • 3
  • 19
  • 29
1

I guess if you don't want these functions to be seen from outside declare them as static.

mikithskegg
  • 806
  • 6
  • 10
  • 1
    *"... seen from outside..."* - From outside of what? The header? The translation unit? – jww Sep 29 '17 at 07:15