Created on 1999-09-09.00:00:00 last changed 204 months ago
[Picked up by evolution group at October 2002 meeting.]
[Picked up by evolution group at October 2002 meeting.]
Note (March, 2008):
The Evolution Working Group recommended closing this issue with no further consideration. See paper J16/07-0033 = WG21 N2173.
9.11 [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.
History | |||
---|---|---|---|
Date | User | Action | Args |
2008-03-17 00:00:00 | admin | set | messages: + msg1634 |
2008-03-17 00:00:00 | admin | set | status: extension -> nad |
2002-11-08 00:00:00 | admin | set | messages: + msg796 |
2002-11-08 00:00:00 | admin | set | status: nad -> extension |
2000-02-23 00:00:00 | admin | set | messages: + msg285 |
2000-02-23 00:00:00 | admin | set | status: open -> nad |
1999-09-09 00:00:00 | admin | create |