views:

134

answers:

3

So I've got an app which compiles fine on windows, linux and a few variations of unix. I recently decided to port it to OSX when I ran into a snag.

I have a template which looks like this:

template<int (&F)(int)>
int safe_ctype(unsigned char c) { return F(c); }

the idea being to prevent sign extension from crashing certain implementations when given input values above 0x7f. It is typically used like this:

safe_ctype<std::isspace>(ch);

This unfortunately doesn't work on OSX (using gcc 4.2). The error has to do with std::isspace not having external linkage and therefore not applicable for templates. It turns out that on OSX, the ctype.h header has all functions (through macros) marked static inline.

Here's my question:

Is it permitted by any relevant standard for functions in the C++ (in this case the parts inherited from C's) standard library to not have external linkage?

EDIT:

I've heard back from apple. Apparently they have a macro to control this behavior. Defining _DONT_USE_CTYPE_INLINE_ prevents the ctype functions from being static inline.

+14  A: 

C++03 §17.4.2.2/1 says:

Entities in the C++ Standard Library have external linkage.

The same is true in C: C99 §7.1.2/6 says:

Any declaration of a library function shall have external linkage.

James McNellis
+1: I love references to the Standard
Chubsdad
A: 

How about using "cctype" (i mean within angle brackets) instead of "ctype.h" Anyways, would be an old-styed header I guess.

Chubsdad
I am using `<cctype>` but the error originates from that including `<ctype.h>`.
Evan Teran
@Evan Teran: Let all of us know how you resolved this issue.
Chubsdad
I've filed a bug report with apple (https://bugreport.apple.com/cgi-bin/WebObjects/RadarWeb.woa/9/wo/6aVZoNoJkJwq5qhwL0J7Bw/10.60). In the meantime I'm simply using a macro to either call the function directly or through the template based on if it is being compiled on OSX. Not an ideal solution, but it is good enough for now.
Evan Teran
+2  A: 

The OS X <ctype.h> header protects the non-standard inline versions with a check that you are not compiling in standards mode.

If you don't tell the compiler you want conformance, you don't get conformance. This is true on almost all platforms, though in different ways.

If you want all the niceties of extensions and what not, and so don't want to require strict conformance, you can define _DONT_USE_CTYPE_INLINE_ before including the header and you will get non-inline versions of the functions with external linkage.

Stephen Canon