Overload resolution with extern “C” linkage

血红的双手。 提交于 2019-12-05 01:15:12

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 (§[dcl.link]/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.

The standard shows the following example:

complex sqrt(complex); // C + + linkage by default
extern "C" {
    double sqrt(double); // C linkage
}

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.

namespace your_project {  // You do use one, right? :)
  void f(int x);
  void f(char x);
  void f(other_overloads x);
}

extern "C"
void f(int x) {
  your_project::f(x);
}
Mark B

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 C++03 7.5/5:

If two declarations of the same function or object specify different linkage specifications (that is, the linkage specifications of these declarations specify different string literals), the program is ill-formed 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 C++03 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.

(This answer applies to C++14; other answers so far are C++03).

It is permitted to use overloading. If there is an extern "C" function definition of some particular name then the following conditions apply (references to C++14 in brackets):

  • The declaration of the extern "C" function must be visible at the point of any declaration or definition of overloads of that function name (7.5/5)
  • There must be no other extern "C" definition of a function or variable with the same name, anywhere. (7.5/6)
  • An overloaded function with the same name must not be declared at global scope. (7.5/6)
  • Within the same namespace as the extern "C" function, there must not be another function declaration with the same name and parameter list. (7.5/5)

If any violation of the above rules occurs in the same translation unit the compiler must diagnose it; otherwise it is undefined behaviour with no diagnostic required.

So your header file might look something like:

namespace foo
{
    extern "C" void bar();
    void bar(int);
    void bar(std::string);
}

The last bullet point says that you cannot overload solely on linkage; this is ill-formed:

namespace foo
{
    extern "C" void bar();
    void bar();               // error
}

However you can do this at different namespaces:

extern "C" void bar();
namespace foo
{
    void bar();
}

in which case , normal rules of unqualified lookup determine whether a call bar() in some code finds ::bar, foo::bar, or ambiguous.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!