This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 116a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-12-19


13. extern "C" for Parameters of Function Templates

Section: 9.11  [dcl.link]     Status: NAD     Submitter: John Spicer     Date: unknown

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

How can we write a function template, or member function of a class template that takes a C linkage function as a parameter when the function type depends on one of the template parameter types?

    extern "C" void f(int);
    void g(char);

    template <class T> struct A {
        A(void (*fp)(T));
    };

    A<char> a1(g);  // okay
    A<int> a2(f);   // error
Another variant of the same problem is:
    extern "C" void f(int);
    void g(char);

    template <class T> void h( void (*fp)(T) );

    int main() {
        h(g);  // okay
        h(f);  // error
    }

Suggested resolution: (John Spicer)

Somehow permit a language linkage to be specified as part of a function parameter declaration. i.e.

    template <class T> struct A {
        A( extern "C" void (*fp)(T) );
    };

    template <class T> void h( extern "C" void (*fp)(T) );
Suggested resolution: (Bill Gibbons)

The whole area of linkage needs revisiting. Declaring calling convention as a storage class was incorrect to begin with; it should be a function qualifier, as in:

    void f( void (*pf)(int) c_linkage );
instead of the suggested:
    void f( extern "C" void (*pf)(int) );
I would like to keep calling convention on the "next round" issues list, including the alternative of using function qualifiers.

And to that end, I suggest that the use of linkage specifiers to specify calling convention be deprecated - which would make any use of linkage specifiers in a parameter declaration deprecated.

Martin Sebor: 9.11 [dcl.link], paragraph 4 says that "A linkage-specification shall occur only in namespace scope..." I'm wondering why this restriction is necessary since it prevents, among other things, the use of the functions defined <cmath> in generic code that involves function objects. For example, the program below is ill-formed since std::pointer_to_binary_function<> takes a pointer to a function with extern "C++" linkage which is incompatible with the type of the double overload of std::pow.

Relaxing the restriction to allow linkage specification in declarations of typedefs in class scope would allow std::pointer_to_binary_function<> ctor to be overloaded on both types (i.e., extern "C" and extern "C++"). An alternative would be to allow for the linkage specification to be deduced along with the type.

    #include <cmath>
    #include <functional>
    #include <numeric>

    int main () {
      double a[] = { 1, 2, 3 };
      return std::accumulate (a, a + 3, 2.0,
        std::pointer_to_binary_function<double, double, double>(std::pow));
    }

Rationale (February, 2014):

EWG determined that no action should be taken on this issue.