 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Falk Tannhäuser Guest
|
Posted: Sat Sep 11, 2004 2:04 am Post subject: Template functions and extern "C"? |
|
|
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 § 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*) = 0;
}
void* toto(void* p) { return p; } // extern "C++" by default
int main()
{
pf = &threadStarter
// g++, Comeau and Dinkum[EDG/C++] (refused by the two latter if
// the template function declaration above is suppressed)
pf = &threadStarter<bar>; // Same as above
#if 0
// Standard conformance check:
pf = &toto; // Accepted by g++ and Dinkum[VC++/C++], refused (correctly,
// 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 (parameter
passing on stack / in registers, in which order / alignment, stack cleanup
by caller or callee, return value passing...). Name mangling prevents linking
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 assignment
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 code
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äuser
---
[ 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 ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|