In a mixed C/C++ project, we need to make a call from C to a C++ function. The function to be called is overloaded as three separate functions, but we can ignore that from the C-side, we just pick the one most suitable and stick to that one.

There's two ways to do this: (1) write a small C++ wrapper with a extern "C" function that forwards the call to the chosen overloaded function, or (2) the hackish way to just declare the one function we want to call from C as extern "C".

The question is, is there any disadvantages (apart from nightmares and bad karma) to go for the second variant? In other words, given three overloaded function, where one is declared as exern "C", should we expect trouble with the C++ side, or is this well defined according to the standard?

Isn't using the word "hackish" to describe a solution a code smell?
–
Travis GockelFeb 1 '11 at 17:56

Yes it's definitely a code smell, a collegue of mine asked me about it and I recommended doing solution 1 as I think that's cleaner. But at the same time I got curious about what is supposed to happen if we went for solution 2... The fact that we have to ask is already a code smell when a less uncertain solution exists :)
–
haraldFeb 1 '11 at 21:49

3 Answers
3

I had said that it was undefined, but rereading the standard, I can't find the language I thought was there. In fact, the example code at §7.5/3 seems to indicate that the result probably is defined -- i.e., you can have other overloads with C++ linkage, as long as there's only one function with "C" linkage. The example they show is:

Two points: 1) being an example, this isn't normative. 2) It doesn't directly state that both those declarations are actually allowed together in the same program. Nonetheless, I think the intent is that it can be viewed as a single fragment of code which gives defined behavior.

After rereading, I believe the language in the standard is specifically written to allow exactly one function with "C" linkage, and an arbitrary number of other functions with "C++" linkage that overload the same name (§7.5/6):

At most one function with a particular name can have C language linkage. Two declarations for a function with C language linkage with the same function name (ignoring the namespace names that qualify it) that appear in different namespace scopes refer to the same function. Two declarations for an object with C language linkage with the same name (ignoring the namespace names that qualify it) that appear in different namespace scopes refer to the same object.

Even if it was allowed by the standard, future maintainers of the code will probably be extremely confused and might even remove the extern "C", breaking the C code (possibly far enough later that the events aren't linkable).

Just write the wrapper.

EDIT:
From 7.5/5:

If two declarations of the same
function or object specify different
linkagespecifications (that is, the
linkagespecifications of these
declarations specify different
stringliterals), the program is
illformed if the declarations appear
in the same translation unit, and the
one definition rule (3.2) applies if
the declarations appear in different
translation units...

I interpret this to not apply since C and C++ functions with the same name aren't actually the same function but this interpretation may be wrong.

Then from 7.5/6:

At most one function with a particular
name can have C language linkage...

This then implies that you could have other, non-C-linkage, functions with the same name. In this case, C++ overloads.

As long as you follow the other rules for extern-C functions (such as their special name requirements), specifying one of the overloads as extern-C is fine according to the standard. If you happen to use function pointers to these functions, be aware that language linkage is part of the function type, and needing a function pointer to this function may decide the issue for you.

Otherwise, I don't see any significant disadvantages. Even the potential disadvantage of copying parameters and return value can be mitigated by compiler- and implementation-specifics that allow you to inline the function – if that is determined to be a problem.

Interesting solution, if I get this right you avoid the entire problem by having all the overloads in a namespace. And a separate non-namespaced function with C-linkage. Not sure if we can easily do that in our project as the C++ code is legacy and originates from another project. Wish I could accept all answers, really...
–
haraldFeb 1 '11 at 21:58

@harald: Generally all functions from a project, even if it is not intended to be used elsewhere as a library, should be in a namespace already.
–
Fred NurkFeb 1 '11 at 22:05