C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Template functions and extern "C"?

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language, library and standards
View previous topic :: View next topic  
Author Message
Falk Tannhäuser
Guest





PostPosted: Sat Sep 11, 2004 2:04 am    Post subject: Template functions and extern "C"? Reply with quote



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 Smile?

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
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language, library and standards All times are GMT
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.