Title
C linkage for static member functions
Status
nad
Section
9.11 [dcl.link]
Submitter
Darin Adler

Created on 1999-09-09.00:00:00 last changed 204 months ago

Messages

Date: 2002-10-15.00:00:00

[Picked up by evolution group at October 2002 meeting.]

Date: 2002-10-15.00:00:00

[Picked up by evolution group at October 2002 meeting.]

Date: 2008-03-15.00:00:00

Note (March, 2008):

The Evolution Working Group recommended closing this issue with no further consideration. See paper J16/07-0033 = WG21 N2173.

Date: 2022-11-20.07:54:16

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:00adminsetmessages: + msg1634
2008-03-17 00:00:00adminsetstatus: extension -> nad
2002-11-08 00:00:00adminsetmessages: + msg796
2002-11-08 00:00:00adminsetstatus: nad -> extension
2000-02-23 00:00:00adminsetmessages: + msg285
2000-02-23 00:00:00adminsetstatus: open -> nad
1999-09-09 00:00:00admincreate