简体   繁体   中英

C++ file-scope static functions

When should I consider using static functions defined at file scope?

I typically use them when the task done in one such function doesn't really belong in member functions of any class and when such a task is only needed (repeatedly) in a certain source file.

Is my usage in line with why this feature exists? Or am I hijacking a concept that's intended for something else?

That's a perfectly valid use of file-scope static functions, but keep in mind that this usage of static has been deprecated for quite some time. It's generally preferred to use anonymous namespaces instead.

I do a similar thing when it make sense to have functions and/of data that are not part of the class interface but rather an implementation detail.

But I don't use the keyword static. Instead, I put the functions and/or data in an unnamed namespace.

First off, the term you are looking for is internal linkage . Your question really should be: "Which entities should have internal linkage?" The static keyword, or alternatively unnamed namespaces, are just implementation mechanisms to achieve internal linkage.

Now the answer should be obvious: All entities that are only required inside one single translation unit may be given internal linkage, and there are benefits in doing so: One is that the compiler can make use of the information that an entity cannot ever be seen by any other translation unit, so it can for example avoid emitting code that might be required otherwise, or inline more aggressively. Another reason is that you minimize the risk of accidental ODR violations if you happen to pick a name that is also used locally in some other TU.

A typical example is like this:

my_lib.hpp:

#ifndef H_MY_LIB
#define H_MY_LIB

namespace foo
{
    void do_an_awesome_thing(void * p, std::size_t n);
}

#endif

my_lib.cpp:

#include "my_lib.hpp"

namespace foo
{
    namespace
    {
        void helper(void * p) { /* ... */ }
        bool aux(std::size_t n, float f) { /* ... */ }

        constexpr char usage[] = R"(This is how you do it...)";
        constexpr float some_factor = 1.25;
    }

    void do_an_awesome_thing(void *p, std::size_t n)
    {
        if (!aux(n, some_factor)) { LOG_AND_DIE(usage); }
        helper(p);
    }
}

Now your can be sure that your translation unit does not impose any undue link-time burden on the remainder of your program.

The placement of the unnamed namespace is a matter of taste; you can either have it inside your usual namespace, or at the top level. The effect is the same.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM