Search code examples
c++functionlinkage

Is it possible to overload functions with extern linkage?


I saw a strange code, in declaration of std::atexit:

extern "C"   int atexit( void (*func)() );
extern "C++" int atexit( void (*func)() ); // ... why are there two functions?

I guess it's some kind of function overloading, but it seems obviously wrong.

What's it? and why is it necessary?


Solution

  • The problem with your source

    This is cppreference being a little misleading.

    Declaring the same function twice with different storage-class-specifiers is illegal and causes a build failure. If you look at the source for libstdc++ (GCC's standard library implementation), you'll see that only the extern "C" version is actually provided.


    The standard's take on this

    Although [C++11: 18.5] lists both declarations, just as does cppreference, this does not mean that both may be used in a single implementation; it means that an implementation may choose to declare either of them: that is, it accounts for [C++11: 17.6.4.3.3/4] which says:

    Each function signature from the Standard C library declared with external linkage is reserved to the implementation for use as a function signature with both extern "C" and extern "C++" linkage [..]

    Also:

    [C++11: 17.6.2.3/2]: Whether a name from the C standard library declared with external linkage has extern "C" or extern "C++" linkage is implementation-defined. It is recommended that an implementation use extern "C++" linkage for this purpose

    The rule is made explicitly clear here:

    [C++11: 7.5/5]: If two declarations declare functions with the same name and parameter-type-list (8.3.5) to be members of the same namespace or declare objects with the same name to be members of the same namespace and the declarations give the names different language linkages, the program is ill-formed; no diagnostic is required if the declarations appear in different translation units. [..]


    Why this can be confusing

    To my mind, this does cause some problems in other places within the standard; for example:

    [C++11: 25.5/2]: The contents are the same as the Standard C library header <stdlib.h> with the following exceptions:

    [C++11: 25.5/3]: The function signature:

    bsearch(const void *, const void *, size_t, size_t,
            int (*)(const void *, const void *));
    

    is replaced by the two declarations:

    extern "C" void *bsearch(const void *key, const void *base,
                             size_t nmemb, size_t size,
                             int (*compar)(const void *, const void *));
    
    extern "C++" void *bsearch(const void *key, const void *base,
                               size_t nmemb, size_t size,
                               int (*compar)(const void *, const void *));
    

    both of which have the same behavior as the original declaration.

    I consider that to be a language defect.