Handmade Hero » Forums » Code » internal (static) vs anonymous namespace
d7samurai
70 posts

innovation through innovation™

#2633 internal (static) vs anonymous namespace
3 years, 8 months ago

Since we're already helping ourselves to a few select C++ conveniences, couldn't we put all the functions marked "internal" inside an anonymous namespace instead, retaining the same effect, or are there reasons not to do this (I know Casey's big on searchability, but that might not matter here, as this just takes one kind of "static" out of the confusion equation anyway)?

software development should be a creative exercise, not a technical ordeal
DaleKim
Dale Kim
22 posts
#2634 internal (static) vs anonymous namespace
3 years, 8 months ago

Seems pretty inconvenient to do that. The advantage of internal is that it's searchable and you can individually mark functions trivially to be that way. With a namespace, you're venturing further into C++ land making C compatibility more difficult and you need to actually move the code around to your namespace block or you need to populate your code with a ton of namespace { ... }.

More difficult to make things "internal", less searchable, more typing, less C compatibility. I'm not sure that there's any reason to do this.
cmuratori
Casey Muratori
810 posts / 1 project

Casey Muratori is a programmer at Molly Rocket on the game 1935 and is the host of the educational programming series Handmade Hero.

#2635 internal (static) vs anonymous namespace
3 years, 8 months ago

Yeah, it seems like a strictly worse option in all respects. Am I missing something?

- Casey
d7samurai
70 posts

innovation through innovation™

#2637 internal (static) vs anonymous namespace
3 years, 8 months ago Edited by d7samurai on Feb. 14, 2015, 11:34 p.m.

Well, that was what the question mark was for..

If C compatibility is a point, then forget it. But the premise was that we're already doing C++ code. And if all functions are marked internal anyway, then the rest of those counterpoints are moot.

Force of habit aside, the point of doing it would obviously be to not have to [remember to] type "internal" all the time; It's LESS typing, not more. And it's just as easy - if not easier - to make things internal. Just place them in the namespace.

If you plan on having a mere 50% of the functions marked internal AND deliberately randomly interspersed throughout the code, then I agree it's not a good idea (the question then is whether THAT is a good idea..).

But if "internal" is the rule and the odd externally visible function is the exception*, then just one big {} around everything is enough. How is that more difficult? It's practically automatic. And what advantage does searchability give you over this? The results that you'd get searching for "internal" are inside that bracket anyway (and vice versa; external functions are outside. But how do you search for non-internal functions scattered around the code?).

Also, I'd argue that it's a structural / readabilty benefit to group the internal functions together. You easily see what parts of the code that are externally visible and not (and the concept of placing the internal functions "inside" something even maps both visually and semantically onto the intent).


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
namespace
{
    void InternalFunctionA() {}
    void InternalFunctionB() {}
    void InternalFunctionC() {}
}

void ExternalFunctionA() {}

internal void InternalFunctionDIfYouMUSTHaveOneDownHereForSomeReason() {}


*Between win32_handmade.cpp and handmade.cpp (day 55) there are

4 externally visible functions (DEBUG_PLATFORM file read/write/free in the former and only one, the DLL exported GAME_UPDATE_AND_RENDER, in the latter).

36 internal functions (plus 8 inline functions that could probably also be made internal).

In other words, except for those 4, everything else could be inside one big bracket in each file. Why would anyone need to search for them? They're there. Less searching. Less typing. Less clutter. Forcing better code organization. Need to make another internal function? Just type it in above the "}". Convenient.

software development should be a creative exercise, not a technical ordeal
DaleKim
Dale Kim
22 posts
#2641 internal (static) vs anonymous namespace
3 years, 8 months ago

d7samurai
Force of habit aside, the point of doing it would obviously be to not have to [remember to] type "internal" all the time; It's LESS typing, not more. And it's just as easy - if not easier - to make things internal. Just place them in the namespace.


Maybe if you're never, ever going to change the linker visibility of the functions. In a unity build, I suppose this is somewhat of a moot point. But if I ever want to make a function go from internal to external linkage (or vice versa) in the anonymous namespace case, this is far more work than simply deleting "internal" from the function signature.

I now have to find the beginning and ending of the definition of the function, cut that out and find a new place in the file to paste it. I lose a lot of ease in the ability to just make something internal vs external with the anonymous namespace case. And trust me, this is not just "a small change". I've had functions that were hundreds of lines long that I wanted to make internal/external and since I did anonymous namespace, it made me want to shoot myself.


d7samurai
If you plan on having a mere 50% of the functions marked internal AND deliberately randomly interspersed throughout the code, then I agree it's not a good idea. The question is whether THAT is a good idea..

But if "internal" is the rule and the odd externally visible function is the exception*, then just one big {} around everything is enough. How is that more difficult? It's practically automatic. And what advantage does searchability give you over this? The results that you'd get searching for "internal" are inside that bracket anyway (and vice versa; external functions are outside. But how do you search for non-internal functions scattered around the code?).


I do agree that if your default programming style is to prefer internal linkage vs external, that there is some level of convenience to using an anonymous namespace, but for the reason I mentioned above (among others), I do not prefer it.


d7samurai
Also, I'd argue that it's a structural / readabilty benefit to group the internal functions together. You easily see what parts of the code that are externally visible and not (and the concept of placing the internal functions "inside" something even maps both visually and semantically onto the intent).


I'm not sure where you're going with the whole mapping semantically onto intent thing... Where the text of my functions are in relation to each other physically in the file have almost no meaning *at all* to me. I just work in chunks of functions and statement lists. To be fair, there is some level of convenience when the functions are small and things that are often used together are near each other, but those functions are often uninteresting.

I spend the lion's share in my time in the large functions that actually do things in the code. Where another large function happens to be in the file has almost no relevance since there can only be two adjacent functions to any definition and any sufficiently large program will surely have more than 1 or 2 interesting functions... And C/C++'s declaration before use model help you any here.


d7samurai
In other words, except for those 4, everything else could be inside one big bracket in each file. Why would anyone need to search for them? They're there. Less searching. Less typing. Less clutter. Forcing better code organization. Need to make another internal function? Just type it in above the "}". Convenient.


It's actually easier to search. WAY easier. Why would you want to search? So you can absolutely be sure that whatever you wanted to be external linkage is external, and the things that are internal are actually internal.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
namespace
{
    // Thousands of lines of function defs preceding...

    void Foo()
    {
        printf("Foo!\n");
    }

    void Bar()
    {
        printf("Bar!\n");
    }

    // Thousands of lines of function defs following...
}

// Thousands of lines of code...

void Baz()
{
    printf("Baz!\n");
}

// Thousands of lines of code...


How can I trivially verify that Foo() and Bar() are internal linkage? Also, suppose that I've intended Baz() to be internal linkage, but mistakenly left it out of my anonymous namespace (as I did above).

grepping for this is just impossible. I've made the notion of internal linkage some range within my text block that is not searchable. Now I have to go inside and manually inspect the source code and start matching up braces. This is way more work than just running grep on my code base and looking for a tag on the function signature that every internally linked function must have.

The searchability and granularity of anonymous namespaces is just not good enough for me to prefer that method specifying of internal linkage.
cmuratori
Casey Muratori
810 posts / 1 project

Casey Muratori is a programmer at Molly Rocket on the game 1935 and is the host of the educational programming series Handmade Hero.

#2642 internal (static) vs anonymous namespace
3 years, 8 months ago

OK, I think I see what OP was saying - you're just trying to cut down on the typing of the word "internal", I guess?

That seems reasonable enough, but I would first want to make sure that it:

1) Causes no debugging issues (like, failure to find things because they're in the namespace or something like this),

2) Does not increase the debug or release PDB files or other related files,

3) Does not slow down the compiler or the linker.

If all those were satisfied, then I'd say it'd be fine. But some extensive testing would have to be done first to determine that that was true (and I don't mean just on Handmade Hero as it is - but rather on some 200k / 300kline source tree that has more like what we'll have at the end of the project).

- Casey
d7samurai
70 posts

innovation through innovation™

#2644 internal (static) vs anonymous namespace
3 years, 8 months ago Edited by d7samurai on April 5, 2017, 2:28 p.m.

Well, people are different. I care a lot about the structure of my code. I care about making it logical, consistent and clean. I like to keep things systematic and organized. I like my code to reflect / represent some mental image / model I have of the overall architecture and program flow, and thus be able to navigate intuitively around it (precisely so I don't have to search so much for stuff).

If you prefer to have your things randomly strewn around and also happen to willy-nilly switch things in and out of "static" status on a regular basis, then obviously having to cut and paste and wade through everything, looking for the end of the file / namespace each time is a huge, huge ordeal that I wouldn't wish upon my worst enemy (and certainly not someone with such a low suicide threshold).

True, I do work in Visual Studio (with a couple of helpful add-ins), which among other things allows me to collapse functions (and namespaces) and view thousands of lines of code as a handful of lines - much like the pseudo-code in my previous post - in a way that gives me a nice overview of the whole file. And from that vantage point I can quite easily select, cut, paste and move large chunks of code wherever I want, so for me those things are just less traumatic to accomplish, I guess.

Here's how a 1391 line file looks to me in a couple of mouse clicks:



I say that beats nexting through a bunch of grep hits in a wall of text any day of the week.

Anyway, I already granted the kind of case you speak of with lots of internal / external interleaving as one where a single anonymous namespace probably isn't the way to go. But then I went on to say that when "static" is the rule and a few odd external functions are the exception, then it might simply be easier to just work inside the namespace and put / hoist one or two things outside of it, once in a blue moon, when you know they need to be externally accessible.

Again, the premise here is a codebase where most functions would be "internal" anyway (though I was under the impression that that was the case with HMH).

Regarding the mapping: I wasn't referring to where functions are in relation to each other in the file (although personally I do consider that when I organize my code). I was referring to having everything internal grouped together in one section and everything exposed externally grouped together in another (i.e. outside the namespace). And since the former would then be "internal" to that namespace and the rest "external" to it, it would map - as in correspond - nicely onto them being internal / external to the translation unit as a whole.

And I think you misunderstood the point about search. What I meant was that you don't need to search for "internal" functions when using an anonymous namespace; all the internal functions are in it and the external ones are not! It's like having an already sorted list of internal and external functions.

How you can trivially verify that Foo() and Bar() are internal and Baz() is external? Well, for one, Foo() and Bar() are indented, and Baz() isn't. Or, in my case, I could just collapse the namespace and see Baz() hanging on the outside. Plus having some intuitive notion about where and how things are placed in the code in general also helps (another reason I like to have a solid, consistent structure behind what I do).

Why would you want to search? So you can absolutely be sure that whatever you wanted to be external linkage is external

So how do you search for externals? That was my point.

Bottom line is that nobody is trying to force you to do things differently. I was just pointing out that in certain cases, especially ones where most functions are internal anyway, it might be an alternative to simply "work inside" an anonymous namespace and keep that one export on the outside.

EDIT: Apparently, you can keep extern "C" declarations like GAME_UPDATE_AND_RENDER inside the namespace and still have them externally visible. More details: http://www.comeaucomputing.com/techtalk/#nostatic

software development should be a creative exercise, not a technical ordeal
d7samurai
70 posts

innovation through innovation™

#2645 internal (static) vs anonymous namespace
3 years, 8 months ago Edited by d7samurai on Feb. 14, 2015, 8:03 a.m.

Oh, hi Casey - didn't know you had responded in between there.. :)

Here's what MSDN says about it:

Unnamed namespaces are a superior replacement for the static declaration of variables. They allow variables and functions to be visible within an entire translation unit, yet not visible externally. Although entities in an unnamed namespace might have external linkage, they are effectively qualified by a name unique to their translation unit and therefore can never be seen from any other translation unit.
https://msdn.microsoft.com/en-us/library/yct4x9k5.aspx

Unnamed namespaces are transparent within their translation unit.

I don't know how they fare when it comes to compilation / linking speed, file bloat and such compared to regular old static.

software development should be a creative exercise, not a technical ordeal
5sw
Sven
33 posts
#2653 internal (static) vs anonymous namespace
3 years, 8 months ago

When doing an unity build I wouldn't bother with static at all. I'd make sure to enable link-time optimization and that only the functions I'd wanted where exported.