Title
extern "C" for Parameters of Function Templates
Status
nad
Section
9.11 [dcl.link]
Submitter
John Spicer

Created on 1998-10-24.00:00:00 last changed 130 months ago

Messages

Date: 2002-10-15.00:00:00

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

Date: 2014-02-15.00:00:00

Rationale (February, 2014):

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

Date: 2022-11-20.07:54:16

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));
    }
History
Date User Action Args
2014-03-03 00:00:00adminsetmessages: + msg4976
2014-03-03 00:00:00adminsetstatus: extension -> nad
2002-11-08 00:00:00adminsetmessages: + msg794
1998-10-24 00:00:00admincreate