10

I have some functions in a namespace I made that are used throughout my program.

In header file:

namespace NQueens
{
    static int heur = 0;
    int CalcHeuristic(char** state, int size);
    void CalcHorzH(char ** state, int &heuristic, int size);
    void CalcColH(char ** state, int &heuristic, int size);
    void CalcDiagH(char ** state, int &heuristic, int size);
    int calcCollisions(int queensPerRow, int size);
}

Everything works fine. However the only function that actually gets called from my outside program code is the CalcHeuristic(char** state, int size) function. This function then calls the other functions itself.

Since these do not belong to a class my compiler will not let me declare the other functions as private. Is there a way to do this? Should I even worry about it?

nwp
  • 9,623
  • 5
  • 38
  • 68
BradStell
  • 371
  • 3
  • 17
  • you want something misterious. Use classes + static methods. – Dmitry Sazonov Oct 05 '15 at 16:25
  • I do use classes and static methods in my code, I like this for certain situations, this just not being one of those situations. – BradStell Oct 05 '15 at 16:40
  • Please express your gratefulness by upvoting/accepting answers, not by editing in "Thank you!" messages. – nwp Oct 05 '15 at 16:46
  • *"Should I even worry about it?"* - That's the most important part of this question. But it cannot be answered by us. It is up to you to decide what things belong to a software component's *interface* and which things belong to its *implementation*. – Christian Hackl Oct 05 '15 at 16:48
  • As a general rule of thumb for any object oriented design you should not expose the function to the outside world except only the intended functions. – Krishna Oza Oct 05 '15 at 16:55
  • @nwp Thanks for your suggestion. However I did upvote/accept the correct answer, I ALSO put in a thank you as an additional reference. 'Christian Hack' thank you for this also. I technically do not need to worry about this since I am the only developer and it is a project that will never be coded on again. However, I just wanted to get more insight into how things are supposed to be executed in proper c++ programming. – BradStell Oct 05 '15 at 16:56
  • @BradStell: For example, `CalcHorzH` might be a useful function to call directly from a lot of other code. So why not expose it? On the other hand, exposing too many functions pollutes an interface and makes it harder to use correctly or easier to use incorrectly. And whatever you expose you have to keep and maintain forever. Interface design is a difficult tradeoff between benefits and liabilities. – Christian Hackl Oct 05 '15 at 17:08

5 Answers5

17

Don't declare them in the header, put them in an anonymous namespace in the implementation file.

Example header:

namespace NQueens
{
    int CalcHeuristic(char** state, int size);
}

Example implementation:

namespace
{
    static int heur = 0;
    void CalcHorzH(char ** state, int &heuristic, int size);
    void CalcColH(char ** state, int &heuristic, int size);
    void CalcDiagH(char ** state, int &heuristic, int size);
    int calcCollisions(int queensPerRow, int size);
}

namespace NQueens
{
    int CalcHeuristic(char** state, int size)
    {
        // ...
    }
}

namespace
{
    void CalcHorzH(char ** state, int &heuristic, int size) {}
    void CalcColH(char ** state, int &heuristic, int size) {}
    void CalcDiagH(char ** state, int &heuristic, int size) {}
    int calcCollisions(int queensPerRow, int size) { return 0; }
}
molbdnilo
  • 64,751
  • 3
  • 43
  • 82
  • This also has the benefit of reduced compile time during development: Changing the internal functions will only recompile the source file, not everything that includes your header. – m8mble Oct 05 '15 at 16:22
  • @molbdnilo can you please give an example of an anonymous namespace? – BradStell Oct 05 '15 at 16:23
  • 2
    @BradStell It may sound fancy, but it's a namespace that has no name (and thus can't be referred to "from the outside"). See edit. – molbdnilo Oct 05 '15 at 16:34
  • Oh ok, so now in the third namespace down in your example (the 2nd anonymous namespace) this is where I provide the implementation of the functions? – BradStell Oct 05 '15 at 16:37
  • @molbdnilo Thank you! This worked and did the trick. Function working normally with the newly hidden methods. – BradStell Oct 05 '15 at 16:39
  • 1
    Why the separation into declarations and definitions within the implementation file? – Christian Hackl Oct 05 '15 at 16:47
  • And how exactly do you put breakpoint into those anonymous namespace functions? Ah? – SergeyA Oct 05 '15 at 16:50
  • @ChristianHackl Habit. I prefer to have internals at the bottom. – molbdnilo Oct 05 '15 at 16:50
  • This also does not gurantee to work. Nowhere it is mandated that two anonymous namespace have the same name. – SergeyA Oct 05 '15 at 16:51
  • @molbdnilo: Fair enough, although I personally think that this looks confusing here. One might think that you are dealing with two different anonymous namespaces. – Christian Hackl Oct 05 '15 at 16:51
  • 2
    @SergeyA: §7.3.1.1: *"all occurrences of `unique` in a translation unit are replaced by the same identifier, and this identifier differs from all other identifiers in the translation unit."* – Christian Hackl Oct 05 '15 at 16:55
  • 1
    @SergeyA as far as they are part of single compilation unit it should not be a problem to define multiple anonymous namespaces. – Krishna Oza Oct 05 '15 at 16:58
  • 1
    @SergeyA Within the same translation unit, it is the same namespace (i.e. it behaves exactly like if it were named). Between translation units, they behave as if their names were unique. – molbdnilo Oct 05 '15 at 17:01
5

No you can't make free standing functions private.
What you can do though is not to declare them in the namespace and use an anonymous namespace in your translation unit:

In header:

namespace NQueens {
    static int heur = 0;
    int CalcHeuristic(char** state, int size);
}

in .cpp:

namespace {
    void CalcHorzH(char ** state, int &heuristic, int size) {
       // Implementation
    }
    void CalcColH(char ** state, int &heuristic, int size) {
        // Implementation
    }
    void CalcDiagH(char ** state, int &heuristic, int size) {
        // Implementation
    }
    int calcCollisions(int queensPerRow, int size) {
        // Implementation
    }
}

Another option is to use a class instead of a namespace, containing all those functions as static function members. You can use all of the usual scope semantics as private, protected and public then.

But IIRC such classes (solely containing static function members), aren't considered good practice in preference of placing the functions free standing into namespaces.

Though if you want to realize kind of protected inheritance, that method could be considered useful.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
4

Use private static methods (pseudocode):

class NQueens
{
public:
  static void CalcHeuristic()
  {
    CalcColH();  // Legal here
  }

private:
  static void CalcColH(){}
}

//...
NQueens::CalcHeuristic(); // Legal
NQueens::CalcColH(); // error

Private - is OOP and it's logical visibility. static or anonymous namespaces - is a link-time visibility.

Dmitry Sazonov
  • 8,801
  • 1
  • 35
  • 61
  • I like this approach and I use this method frequently in my code. In this project however I wanted to experiment with standalone functions, when I came into the problem I posted about. – BradStell Oct 05 '15 at 16:52
2

You can't make free-standing functions private. But you can define them as static in your cpp file and do not provide their prototypes in .h file, so that outside callers would not be able to call them.

Edit. To all static haters here, here is something to consider. If you want to declare your functions before defining them (which might be because it is a good practice, or a neccesity since one is calling the another) you will have to open anonymous namespace, declare 'hidden' function, close the namespace, define your visible functions, open anonymous space again, define hidden functions.

Now, while with the compilers I looked for, two anonymous namespace have the same name and this works, this is not guranteed.

Another thing with anonymous namespaces - try putting a breakpoint into thier functions.

SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • 2
    `static` is deprecated for such things. You should use anonymous namespaces instead. Anyway, `private` is OOP thing. And `static` - is not logical visibility, but link-time visibility. (P.S. i didn't downvote) – Dmitry Sazonov Oct 05 '15 at 16:19
  • 3
    static has been undeprecated, in case you didn't notice. – SergeyA Oct 05 '15 at 16:20
  • Yes, I tried this and it does not work. my compiler complains about the functions not being declared in this scope. – BradStell Oct 05 '15 at 16:22
  • 1
    You are doing something wrong here. Static does work. – SergeyA Oct 05 '15 at 16:26
  • @SaZ, OOP is not class-keyword-related-stuff thing – Lol4t0 Oct 05 '15 at 16:28
  • anonymous namespace'd functions and structures are difficult to convince a degugger to decode - I like static. – mksteve Oct 05 '15 at 16:30
  • You are defending `static` with "anonymous namespace doesn't work". Unfortunately that is no argument for `static`, just against "anonymous namespace". Failing at link time seems a bit late and would confuse at least me. – nwp Oct 05 '15 at 16:30
  • @nwp, would you clarify what do you mean by 'failing at link time' here? – SergeyA Oct 05 '15 at 16:42
  • If I use `static` and call the function from where I am not supposed to call it I get a linker error saying the function could not be found, correct? This is worse (not much) than a compile time error saying the function is private or inaccessible. – nwp Oct 05 '15 at 16:44
  • @nwp. No, why? You simply do not have any declarations of those static functions visible outside! – SergeyA Oct 05 '15 at 16:49
  • So `static` or not doesn't really matter, you just put the whole function in the `.cpp` and therefore it doesn't exist for outsiders. Somehow I though you did something with `static` in the header file. Sorry about the confusion. – nwp Oct 05 '15 at 16:51
  • @nwp, if you do not mark it static (or put into anon namespace which I do not advocate for for several reasons) it will still be a visible symbol, polluting the symbols for the whole project. – SergeyA Oct 05 '15 at 16:52
  • 2
    Two anonymous namespace *are* guaranteed to have the same name in the same translation unit. See C++ standard §7.3.1.1: *"all occurrences of `unique` in a translation unit are replaced by the same identifier, and this identifier differs from all other identifiers in the translation unit."* – Christian Hackl Oct 05 '15 at 16:57
  • *"Another thing with anonymous namespaces - try putting a breakpoint into thier functions."* - Works perfectly with MSVC 2013. – Christian Hackl Oct 05 '15 at 17:00
  • @ChristianHackl, probably MSVC is smart here. gdb is giving really hard time. – SergeyA Oct 05 '15 at 17:01
  • @SergeyA: How exactly does it give you a hard time? I must say I never tried it, but I would expect it to work perfectly. Is the breakpoint not hit? – Christian Hackl Oct 05 '15 at 17:03
  • @SergeyA You are actually confusing the semantics of `static` in C and C++ it seems. The equivalent of C `static` in a translation unit in C++ is an anonymous namespace in a TU. See one of my most downvoted questions about this topic [here](http://stackoverflow.com/questions/29224679/c-static-keyword-vs-c-private-scope). Feel free to downvote again, but I think it's mostly downvoted because of revengers targeting. – πάντα ῥεῖ Oct 05 '15 at 17:28
  • I am not confusing anything. – SergeyA Oct 05 '15 at 17:33
  • @ChristianHackl, it can't find the function. You need to get the actual symbol name (by using nm) and give it to the gdb to put a breakpoint into it. – SergeyA Oct 05 '15 at 17:34
  • @SergeyA I have also put a breakpoint into my code using the anonymous namespaces and it works just fine. – BradStell Oct 05 '15 at 21:36
  • @BradStell, I suppose, you are using MSVC as well. – SergeyA Oct 05 '15 at 21:37
  • @SergeyA Why do people oppose static use? did you learn anything new in last 2 years? – Ali Mar 13 '18 at 12:34
  • @Ali, no, I am still at loss why. – SergeyA Mar 13 '18 at 13:57
  • @SergeyA I think it is not discouraged for function use but discouraged for user data type and then people end up generalizing it. My source Selected answer for [link1](https://stackoverflow.com/questions/4726570/deprecation-of-the-static-keyword-no-more) [link2](https://stackoverflow.com/questions/4422507/superiority-of-unnamed-namespace-over-static) – Ali Mar 13 '18 at 15:16
2

If the functions have to be templates or inline, the typical solution is to put them in a namespace called detail, and assume people won't access them.

Otherwise, just don't declare them in the header file.