Topic: Template functions and extern "C"?


Author: tannhauser86549spam@free.fr (=?ISO-8859-1?Q?Falk_Tannh=E4user?=)
Date: Sat, 11 Sep 2004 02:04:38 GMT
Raw View
A few days ago, during a discussion in fr.comp.lang.c++, the question
arose whether a template function can be 'extern "C"'.
Even if the language syntax doesn't seem to allow declaring such a
function directly, a declaration through a typedef would be possible.

First example:
______________________________________________________________
extern "C" typedef void* pthreadEntryFunc(void*);

template<typename T>
struct wrap_pthreadEntry
{
  static pthreadEntryFunc externCfunc; // declaration
};

template<typename T>
void* wrap_pthreadEntry<T>::externCfunc(void* p) // definition
{
  return static_cast<T*>(p)->memfunc();
}
______________________________________________________________

Here, the standard =A7 7.5/4 is very clear: "A C language linkage is
ignored for the names of class members and the member function type of
class member functions." and the example given thereafter in that
paragraph, although showing a non-templated class, is analogous to
the above code.


However, how about this one:
_________________________________________________________________________=
__

#include <iostream>
#include <ostream>

extern "C" typedef void* pthreadEntryFunc(void*);
template<typename T> pthreadEntryFunc threadStarter; // declaration

template<typename T> void* threadStarter( void* p ) // definition
{
  return static_cast<T*>( p )->memfunc() ;
}

struct foo
{
  foo* memfunc() { std::cout << "foo" << std::endl; return this; }
};

struct bar
{
  bar* memfunc() { std::cout << "bar" << std::endl; return this; }
};

extern "C"
{
  void* (*pf)(void*) =3D 0;
}

void* toto(void* p) { return p; } // extern "C++" by default

int main()
{
  pf =3D &threadStarter<foo>; // Refused by Dinkum[VC++/C++], accepted by
     // g++, Comeau and Dinkum[EDG/C++] (refused by the two latter if
     // the template function declaration above is suppressed)
  pf =3D &threadStarter<bar>; // Same as above

#if 0
  // Standard conformance check:
  pf =3D &toto; // Accepted by g++ and Dinkum[VC++/C++], refused (correct=
ly,
              // according to the standard) by Comeau and Dinkum[EDG/C++]
#endif
  return 0;
}
_________________________________________________________________________=
__

I'm aware that that the linkage specification 'extern "C"' influences 2
different potential sources of incompatibility: name mangling (support
type-safe linkage and overloading in C++) and calling convention (paramet=
er
passing on stack / in registers, in which order / alignment, stack cleanu=
p
by caller or callee, return value passing...). Name mangling prevents lin=
king
a "C" call against a C++ function symbol definition but would not affect
a call from "C" of a C++ function through a pointer. However, different
calling conventions prevent correct calls even through pointers, which is
why the C++ standard makes the linkage specification part of the function
type so that an assignment of an 'extern "C++"' function to an 'extern "C=
"'
function pointer becomes a 'type mismatch' error. (On compilers using
compatible calling conventions, it may make sense to allow said assignmen=
t
as a non-conforming, non-portable extension.)

Interesting enough, neither compiler accepts
  namespace A { extern "C" void haha() {} }
  namespace B { extern "C" void haha() {} }
which means they all correctly detect duplicate symbols, and consequently=
,
they do mangle the template function name provided they compile it.

My question: Which one of the compilers I tested is right? Should the cod=
e
above compile, and should the template instantiations always be correctly
callable from "C" through a pointer - let's say, would they be a valid
argument for pthread_create, providing it with a type-safe wrapper :-)?

Falk Tannh=E4user

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]