This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 118e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2025-11-05
[Picked up by evolution group at October 2002 meeting.]
9.12 [dcl.link] paragraph 4 says,
A C language linkage is ignored for the names of class members and the member function types of class member functions.This makes good sense, since C linkage names typically aren't compatible with the naming used for member functions at link time, nor is C language linkage function type necessarily compatible with the calling convention for passing this to a non-static member function.
But C language linkage type (not name) for a static member function is invaluable for a common programming idiom. When calling a C function that takes a pointer to a function, it's common to use a private static member function as a "trampoline" which retrieves an object reference (perhaps by casting) and then calls a non-static private member function. If a static member function can't have a type with C language linkage, then a global or friend function must be used instead. These alternatives expose more of a class's implementation than a static member function; either the friend function itself is visible at namespace scope alongside the class definition or the private member function must be made public so it can be called by a non-friend function.
Suggested Resolution: Change the sentence cited above to:
A C language linkage is ignored for the names of class members and the member function types of non-static class member functions.The example need not be changed because it doesn't involve a static member function.
The following workaround accomplishes the goal of not exposing the class's implementation, but at the cost of significant superstructure and obfuscation:
// foo.h
extern "C" typedef int c_func(int);
typedef int cpp_func(int);
class foo
{
private:
c_func* GetCallback();
static int Callback(int);
};
// foo.cpp
#include "foo.h"
// A local pointer to the static member that will handle the callback.
static cpp_func* cpp_callback=0;
// The C function that will actually get registered.
extern "C" int CFunk(int i)
{
return cpp_callback(i);
}
c_func* foo::GetCallback()
{
cpp_callback = &Callback; // Only needs to be done once.
return &CFunk;
}
Rationale (10/99): The Standard correctly reflects the intent of the Committee.
Note (March, 2008):
The Evolution Working Group recommended closing this issue with no further consideration. See paper J16/07-0033 = WG21 N2173.