I may be a little late to know this standard statement, after seeing the SO answer:
[C++11: 7.5/1]
Two function types with different language linkages are distinct types even if they are otherwise identical.
which means, given:
void f1();
extern "C" void f2();
decltype(f1)
is not the same as decltype(f2)
A reason that I wasn't aware of it until now is that the major compilers (e.g. g++, clang, vc++...) don't respect this rule. See LIVE DEMO.
But I believe most people (include me) will be happier with the current nonconformant behavior. If a compiler follows the standard, many codes that bridge C and C++ would be broken.
Consider this example:
A library provides C API:
#ifdef __cplusplus
extern "C" {
#endif
void registerCallbackInC(void(*callback)(void*));
#ifdef __cplusplus
}
#endif
To use the library in C++:
void f1(void*)
{
...
}
extern "C" void f2(void*)
{
...
}
registerCallbackInC(f1); // invalid, f1 has C++ linkage
registerCallbackInC(f2); // OK
To use registerCallbackInC
, the callback
must have C-linkage as well, however, we can't use extern "C"
with template:
extern "C"
{
template<class T>
void f(void*); // invalid
}
template<class T>
extern "C" void f2(void*); // invalid
template<class T>
struct F
{
extern "C" static void f(void*); // invalid
};
This makes it impossible to synthesize a C callback using template, should I consider the requirement a standard defect?
The only restriction on templates is that the name cannot have C linkage, there is no restriction on its type, so you can use a typedef for a C linkage function in the first declaration of the template.