Need of clarification - Thinking in C++ Vol 2 - Practical Programming

M

ManicQin

The entire text is linked down...

I came across the next remark:
"The reason, albeit obscure, is that a library implementation is
allowed to give C linkage (meaning that the function name does not
contain all the auxiliary information[56] that normal C++ functions
do) to functions inherited from the C language. If this is the case,
the cast fails because transform is a C++ function template and
expects its fourth argument to have C++ linkage and a cast is not
allowed to change the linkage. What a predicament!"

http://www.linuxtopia.org/online_bo...rogramming/c++_practical_programming_115.html

I'm guessing that it refers to the function signature can you direct
me to resources about the differences?

Thanks
 
B

Bo Persson

ManicQin said:
The entire text is linked down...

I came across the next remark:
"The reason, albeit obscure, is that a library implementation is
allowed to give C linkage (meaning that the function name does not
contain all the auxiliary information[56] that normal C++ functions
do) to functions inherited from the C language. If this is the case,
the cast fails because transform is a C++ function template and
expects its fourth argument to have C++ linkage and a cast is not
allowed to change the linkage. What a predicament!"

http://www.linuxtopia.org/online_bo...rogramming/c++_practical_programming_115.html

I'm guessing that it refers to the function signature can you direct
me to resources about the differences?

Thanks

It just says that functions from the C library might actually be C
functions, and not C++ functions. As C++ functions can be overloaded,
they are allowed to be different. The standard doesn't say how.


Bo Persson
 
J

jason.cipriani

I'm guessing that it refers to the function signature can you direct
me to resources about the differences?

It is referring to both the mangled name of the functions after they
are compiled (i.e. the name the function is given in the compiled
object file; a name which is meaningful only to the linker and is not
generally the same as the name you have given the function -- in C the
mangling is relatively standard, in C++ it is far more complex) and,
more relevant to that example in the text, the calling convention used
when calling the function (e.g. the MS compiler's __fastcall,
__stdcall extension keywords, Borland's __fastcall which is different
than MS __fastcall, etc). .

You'll want to consult the documentation for the specific compiler you
are curious about. AFAIK (although I never looked very hard) nobody
has put together a huge summary of all the different calling
conventions and name mangling schemes that different compilers
support / use.

What are you trying to do that you want to know those details?

If you are just trying to learn for the sake of learning, you can find
the info you want in your compiler's documentation, like I mentioned
-- but you can also rest assured that you generally don't need to
think about the technical specifics, you only need to be aware that
different types of linkage exist.

Jason
 
M

ManicQin

It is referring to both the mangled name of the functions after they
are compiled (i.e. the name the function is given in the compiled
object file; a name which is meaningful only to the linker and is not
generally the same as the name you have given the function -- in C the
mangling is relatively standard, in C++ it is far more complex) and,
more relevant to that example in the text, the calling convention used
when calling the function (e.g. the MS compiler's __fastcall,
__stdcall extension keywords, Borland's __fastcall which is different
than MS __fastcall, etc). .

You'll want to consult the documentation for the specific compiler you
are curious about. AFAIK (although I never looked very hard) nobody
has put together a huge summary of all the different calling
conventions and name mangling schemes that different compilers
support / use.

What are you trying to do that you want to know those details?

If you are just trying to learn for the sake of learning, you can find
the info you want in your compiler's documentation, like I mentioned
-- but you can also rest assured that you generally don't need to
think about the technical specifics, you only need to be aware that
different types of linkage exist.

Jason

I was just brushing up on my templates nothing more. I don't really
think that I will need to pass a pointer to template function but it
always fun to bore into c++...
Thanks! I'll look into the compiler documents.
 
J

James Kanze

The entire text is linked down...
I came across the next remark:
"The reason, albeit obscure, is that a library implementation is
allowed to give C linkage (meaning that the function name does not
contain all the auxiliary information[56] that normal C++ functions
do) to functions inherited from the C language. If this is the case,
the cast fails because transform is a C++ function template and
expects its fourth argument to have C++ linkage and a cast is not
allowed to change the linkage. What a predicament!"

The fourth argument of std::transform is a simple template type.
It can be *anything* for which the operator() is legal, with a
single InputIteartor::value_type argument and whose return value
can be assigned to the OutputIterator, i.e. if *result = op(
*first ), the type is legal. There's absolutely no problem with
the function tolower() in <cctype> as an argument in this
regard, whether it be `extern "C"' or not. (Almost: more on
that later.)

The problem is that any C++ header (including <algorithm>, which
is required to use std::transform) may include any other C++
header, including <locale>. <iostream> header, or any other
standard C++ header, may include <locale>. (The statement in
the quoted page that "the <iostream> header also makes available
a two-argument version of tolower() and toupper()" is simply
false. The <iostream> header, or any other standard C++ header,
may include <locale>. And it is <locale> which declares the
function template tolower.

The quoted statement is true as far as it goes, of course: if
tolower has "C" linkage, you have to cast it to `extern "C" int
(*)( int )' (and I don't think you can throw in an extern "C" in
a cast; so you probably have to define the type with a typedef
in an `extern "C" {}' block somewhere earlier). An easier
solution would be to include <ctype.h> (rather than <cctype>),
and specify ::tolower; the function template is guaranteed to be
in std::, and not in the global namespace, and including
<ctype.h> (but not <cctype>) guarantees that the C function will
be found by name lookup in the global namespace. (Note that if
you haven't got a `using namespace std ;' floating around
somewhere, just tolower should work as well, since the compiler
shouldn't look in std:: in this case.)

This solves the syntax problem, and gets the code to compile.
Of course, it still isn't correct---all you've done is convert a
compile time error into undefined behavior. For historical
reasons, the requirements of the C version of tolower are that
the argument be either EOF or in the range [0...UCHAR_MAX].
Dereferencing an std::string::iterator (which obviously,
transform will do) results in a char, and passing a char to this
function, in implementations where plain char is signed, results
in undefined behavior (unless, of course, you've verified before
hand that all of the values really are positive).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,138
Latest member
NevilleLam
Top