23

I jumped into winnt.h and I found out the code as following:

extern "C++" // templates cannot be declared to have 'C' linkage
template <typename T, size_t N>
char (*RtlpNumberOf( UNALIGNED T (&)[N] ))[N];

I'd like to ask questions as following:

  1. how does extern "C++" work?
  2. is this portable among GCC, and Clang?
  3. can all templates be exported with this syntax?

With question 3, I mean that can I separate declearation and definition of the templates, and then generate a dynamic link for the template without actually give the implementation by using this trick?

uchar
  • 2,552
  • 4
  • 29
  • 50
Adam
  • 1,684
  • 1
  • 19
  • 39
  • Good question! Very limited information about this can be found here: http://msdn.microsoft.com/en-us/library/0603949d.aspx – Nemanja Boric Jun 15 '14 at 13:00
  • @NemanjaBoric I've tried MSDN, but found nothing about `extern "C++"` there. – Adam Jun 15 '14 at 13:01
  • 1
    Presumably this is inside a region of `extern "C"`. In C++03 template instantiations always had extern linkage. I'm not sure how in C++11 this is done for instantiation on local types, but presumably in about the same way as for things in an anonymous namespace. So apparently the above does nothing except to *cancel* the implicit `extern "C"` of the region this declaration is placed in. – Cheers and hth. - Alf Jun 15 '14 at 13:01
  • It seems that C++ is a default linkage used in C++: From: http://en.cppreference.com/w/cpp/language/language_linkage – Nemanja Boric Jun 15 '14 at 13:05

2 Answers2

23

Well, extern "C++" won't work in C, of course (though some compilers might support it as an extension). So it only makes sense to use it in C++.

That's because in the case of multiple nested extern linkage specifiers, the innermost one takes effect. So if you have a header file surrounded with extern "C", you can use extern "C++" to temporarily break out of it and declare something with C++ linkage.

It makes the most sense when you want to provide a generally C interface for a C++ library, but you also want to provide C++ helper bits for people actually using it in C++. So you'd put #ifdef __cplusplus \ extern "C" { \ #endif around the header as a whole, and then you ifdef-in those bits with extern "C++" to revert to C++ linkage.

Sneftel
  • 40,271
  • 12
  • 71
  • 104
  • 2
    The Win32 API, which is where winnt.h comes from, is a C-based API. – Remy Lebeau Jun 15 '14 at 17:23
  • 1
    @RemyLebeau Exactly. And yet the header files are designed to be usable from C++, and (to a very limited extent) to take advantage of C++-only features. – Sneftel Jun 15 '14 at 17:50
  • A **very** limited extent. – Remy Lebeau Jun 15 '14 at 18:02
  • So, is there anyone who can answer question 3 that `can all templates be exported with this syntax?`. Usually, templates should only work if implements are also included in the included files. – Adam Jun 19 '14 at 16:33
  • @Adam `extern C++` isn't a cheat code to make tempates easier to deal with. (If it was, you would've heard of it before now.) This is a special case, because the templated function doesn't actually need a definition in order to fulfill its purpose. – Sneftel Jun 19 '14 at 22:05
5
  1. It works by forcing the compiler to use C++ linkage when the surrounding code uses C linkage by default (e.g., you include winnt.h in a C program).
  2. Yes, it should be portable.
  3. Yes they can. There is not much use for "extern "C++"" in C++ programs because the linkage is "C++" anyway. It makes sense to use "extern "C++"" only if there is a good chance that your C++ code will be included into a C code.
Oleg
  • 1,037
  • 7
  • 13
  • 2
    Most likely this `extern "C++"` is in an `extern "C"` block. If not included, the function would attempt to have C linkage. – chris Jun 15 '14 at 13:06