473,406 Members | 2,710 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,406 software developers and data experts.

Casting function pointers to and from void*

I want to make a generic interface between a scripting language and native code,
the native code and the interpreter will both be written in C++. The interpreter
will probably be implemented as a subset of C/C++, thus will have the same
syntax as C/C++.

Somehow the interpreted code must be able to store generic function pointers
because there is no way for the interpreter to know every possible function
signature in advance. I was thinking about casting them to void* for this
purpose.

The interpreted function will be provided with the generic function pointer, and
the function prototype as text. The interpreter will prepare the stack itself
based on this function prototype. What I want to end up with is a simple
interface for users of the interpreter that is identical to the interface for
the native code users.

In other words if the function prototype is:
int FunctionName(int N);
I want uses of my interpreter to be able to specify:
int Result = FunctionName(56);
when they are calling the native code functions.

What kind of C++ syntax will be needed for this?
Jan 5 '07 #1
28 16413

Peter Olcott wrote:
I want to make a generic interface between a scripting language and native code,
the native code and the interpreter will both be written in C++. The interpreter
will probably be implemented as a subset of C/C++, thus will have the same
syntax as C/C++.

Somehow the interpreted code must be able to store generic function pointers
because there is no way for the interpreter to know every possible function
signature in advance. I was thinking about casting them to void* for this
purpose.

The interpreted function will be provided with the generic function pointer, and
the function prototype as text. The interpreter will prepare the stack itself
based on this function prototype. What I want to end up with is a simple
interface for users of the interpreter that is identical to the interface for
the native code users.

In other words if the function prototype is:
int FunctionName(int N);
I want uses of my interpreter to be able to specify:
int Result = FunctionName(56);
when they are calling the native code functions.

What kind of C++ syntax will be needed for this?
I don't understand your problem as stated but maybe boost::function
will aid you.

Jan 5 '07 #2
On Fri, 05 Jan 2007 10:21:46 -0600, Peter Olcott wrote:
I want to make a generic interface between a scripting language and native code,
the native code and the interpreter will both be written in C++. The interpreter
will probably be implemented as a subset of C/C++, thus will have the same
syntax as C/C++.

Somehow the interpreted code must be able to store generic function pointers
because there is no way for the interpreter to know every possible function
signature in advance. I was thinking about casting them to void* for this
purpose.

The interpreted function will be provided with the generic function pointer, and
the function prototype as text. The interpreter will prepare the stack itself
based on this function prototype. What I want to end up with is a simple
interface for users of the interpreter that is identical to the interface for
the native code users.

In other words if the function prototype is:
int FunctionName(int N);
I want uses of my interpreter to be able to specify:
int Result = FunctionName(56);
when they are calling the native code functions.

What kind of C++ syntax will be needed for this?
You can't cast a pointer to a function to a pointer to an object.
reinterpret_cast can convert between two pointers to different functions
only.
Jan 5 '07 #3

"Philipp Reh" <se**@s-e-f-i.dewrote in message
news:45********@news.uni-siegen.de...
On Fri, 05 Jan 2007 10:21:46 -0600, Peter Olcott wrote:
>I want to make a generic interface between a scripting language and native
code,
the native code and the interpreter will both be written in C++. The
interpreter
will probably be implemented as a subset of C/C++, thus will have the same
syntax as C/C++.

Somehow the interpreted code must be able to store generic function pointers
because there is no way for the interpreter to know every possible function
signature in advance. I was thinking about casting them to void* for this
purpose.

The interpreted function will be provided with the generic function pointer,
and
the function prototype as text. The interpreter will prepare the stack itself
based on this function prototype. What I want to end up with is a simple
interface for users of the interpreter that is identical to the interface for
the native code users.

In other words if the function prototype is:
int FunctionName(int N);
I want uses of my interpreter to be able to specify:
int Result = FunctionName(56);
when they are calling the native code functions.

What kind of C++ syntax will be needed for this?

You can't cast a pointer to a function to a pointer to an object.
reinterpret_cast can convert between two pointers to different functions
only.
Is there any standard C++ way to accomplish what I need to accomplish?
Jan 5 '07 #4

"Philipp Reh" <se**@s-e-f-i.dewrote in message
news:45********@news.uni-siegen.de...
On Fri, 05 Jan 2007 10:21:46 -0600, Peter Olcott wrote:
>I want to make a generic interface between a scripting language and native
code,
the native code and the interpreter will both be written in C++. The
interpreter
will probably be implemented as a subset of C/C++, thus will have the same
syntax as C/C++.

Somehow the interpreted code must be able to store generic function pointers
because there is no way for the interpreter to know every possible function
signature in advance. I was thinking about casting them to void* for this
purpose.

The interpreted function will be provided with the generic function pointer,
and
the function prototype as text. The interpreter will prepare the stack itself
based on this function prototype. What I want to end up with is a simple
interface for users of the interpreter that is identical to the interface for
the native code users.

In other words if the function prototype is:
int FunctionName(int N);
I want uses of my interpreter to be able to specify:
int Result = FunctionName(56);
when they are calling the native code functions.

What kind of C++ syntax will be needed for this?

You can't cast a pointer to a function to a pointer to an object.
reinterpret_cast can convert between two pointers to different functions
only.
void Test() {
printf("Hello World!\n");
}

void (*pf)() = Test;

void* vp = (void*) pf;

This all compiles and executes correctly on my compiler.

// All I need now is something like:
goto *vp;
// sets the instruction pointer to the address contain in vp.

Is there anyway that anything like this can be done in standard C++ ???
Jan 5 '07 #5
Peter Olcott <No****@seescreen.comwrote:
void Test() {
printf("Hello World!\n");
}

void (*pf)() = Test;

void* vp = (void*) pf;

This all compiles and executes correctly on my compiler.
Even though it *seems* to work, it is not correct.

http://www.parashift.com/c++-faq-lit....html#faq-33.8

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
Jan 11 '07 #6

"Marcus Kwok" <ri******@gehennom.invalidwrote in message
news:eo**********@news-int2.gatech.edu...
Peter Olcott <No****@seescreen.comwrote:
>void Test() {
printf("Hello World!\n");
}

void (*pf)() = Test;

void* vp = (void*) pf;

This all compiles and executes correctly on my compiler.

Even though it *seems* to work, it is not correct.
It indeed does work, I checked the generated assembly language. It only has to
work on a single platform/compiler. When getting the job done requires breaking
the rules, the rules must be broken.
>
http://www.parashift.com/c++-faq-lit....html#faq-33.8

--
Marcus Kwok
Replace 'invalid' with 'net' to reply

Jan 11 '07 #7
Peter Olcott wrote:
When getting the job done requires breaking the rules, the rules must be
broken.
Please don't blame the job when it's you who decide to break the rules.

--
Salu2
Jan 11 '07 #8
Peter Olcott <No****@seescreen.comwrote:
>
"Marcus Kwok" <ri******@gehennom.invalidwrote in message
news:eo**********@news-int2.gatech.edu...
>Peter Olcott <No****@seescreen.comwrote:
>>void Test() {
printf("Hello World!\n");
}

void (*pf)() = Test;

void* vp = (void*) pf;

This all compiles and executes correctly on my compiler.

Even though it *seems* to work, it is not correct.

It indeed does work, I checked the generated assembly language. It only has to
work on a single platform/compiler. When getting the job done requires breaking
the rules, the rules must be broken.
Sure, but then it is no longer Standard C++. Sorry, I don't have an
answer to your real question. Maybe someone on a group for your
platform or compiler will have a suggestion that is known to work for
your situation.

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
Jan 11 '07 #9

"Julián Albo" <JU********@terra.eswrote in message
news:45********@x-privat.org...
Peter Olcott wrote:
>When getting the job done requires breaking the rules, the rules must be
broken.

Please don't blame the job when it's you who decide to break the rules.

--
Salu2
I don't have to get my system working in theory, I have to get it working in
practice. If it does not work in theory yet does work in practice, then the
theory is discarded.
Jan 11 '07 #10

"Marcus Kwok" <ri******@gehennom.invalidwrote in message
news:eo**********@news-int2.gatech.edu...
Peter Olcott <No****@seescreen.comwrote:
>>
"Marcus Kwok" <ri******@gehennom.invalidwrote in message
news:eo**********@news-int2.gatech.edu...
>>Peter Olcott <No****@seescreen.comwrote:
void Test() {
printf("Hello World!\n");
}

void (*pf)() = Test;

void* vp = (void*) pf;

This all compiles and executes correctly on my compiler.

Even though it *seems* to work, it is not correct.

It indeed does work, I checked the generated assembly language. It only has
to
work on a single platform/compiler. When getting the job done requires
breaking
the rules, the rules must be broken.

Sure, but then it is no longer Standard C++. Sorry, I don't have an
answer to your real question. Maybe someone on a group for your
platform or compiler will have a suggestion that is known to work for
your situation.
I was able to infer that casting to a specific function pointer type would not
generally be possible. It would not generally be possible because the function
pointer requires the compile time support of preparing the stack.
>
--
Marcus Kwok
Replace 'invalid' with 'net' to reply

Jan 11 '07 #11

Peter Olcott wrote:
I don't have to get my system working in theory, I have to get it working in
practice. If it does not work in theory yet does work in practice, then the
theory is discarded.
The problem you create for yourself when you take this approach is that
you have no way of knowing for how long your solution will continue to
work in practice. Examining the generated assembly language is a valid
way of checking that the behaviour in practice of your code is what you
want when the behaviour in theory is formally undefined. However,
unless your compiler documents the behaviour in practice as an
extension (which it may well do), you have no way of knowing how stable
the behaviour in practice is in the face of changes, such as compiler
options, debug vs release build, or a change in the code itself. Your
code is potentially very brittle. Every time you change something and
recompile, you have to reexamine the generated assembly language to see
if you still have the behaviour in practice that you need.

Only you know how likely such changes and the associated need to
recompile are, so only you are in a position to assess the relative
costs of losing robustness in the code vs. redesigning to avoid the
problem in the first place. But it is an assessment you must make.

Gavin Deane

Jan 12 '07 #12

Marcus Kwok wrote:
Peter Olcott <No****@seescreen.comwrote:

"Marcus Kwok" <ri******@gehennom.invalidwrote in message
news:eo**********@news-int2.gatech.edu...
Peter Olcott <No****@seescreen.comwrote:
void Test() {
printf("Hello World!\n");
}

void (*pf)() = Test;

void* vp = (void*) pf;

This all compiles and executes correctly on my compiler.

Even though it *seems* to work, it is not correct.
It indeed does work, I checked the generated assembly language. It only has to
work on a single platform/compiler. When getting the job done requires breaking
the rules, the rules must be broken.

Sure, but then it is no longer Standard C++. Sorry, I don't have an
answer to your real question. Maybe someone on a group for your
platform or compiler will have a suggestion that is known to work for
your situation.
Function-to-object pointer conversions have been added to standard C++
as a "conditionally supported" conversion using reinterpret_cast<>:

"Converting a pointer to a function into a pointer to an object type or
vice versa is conditionally-supported. The meaning of such a conversion
is implementation defined, except that if an implementation supports
conversions in both directions, converting an rvalue of one type to the
other type and back, possibly with different cv-qualification, shall
yield the original pointer value." [expr.reinterpret.cast/8]

Conditionally-supported behavior is one that an implementation is not
required to support. But an implementation does support the feature
must then implement the feature as specified.

Greg

Jan 12 '07 #13
Gavin Deane wrote:
Peter Olcott wrote:
>I don't have to get my system working in theory, I have to get it working in
practice. If it does not work in theory yet does work in practice, then the
theory is discarded.

The problem you create for yourself when you take this approach is that
you have no way of knowing for how long your solution will continue to
work in practice. Examining the generated assembly language is a valid
way of checking that the behaviour in practice of your code is what you
want when the behaviour in theory is formally undefined. However,
unless your compiler documents the behaviour in practice as an
extension (which it may well do), you have no way of knowing how stable
the behaviour in practice is in the face of changes, such as compiler
options, debug vs release build, or a change in the code itself. Your
code is potentially very brittle. Every time you change something and
recompile, you have to reexamine the generated assembly language to see
if you still have the behaviour in practice that you need.

Only you know how likely such changes and the associated need to
recompile are, so only you are in a position to assess the relative
costs of losing robustness in the code vs. redesigning to avoid the
problem in the first place. But it is an assessment you must make.
Despite all these dire threats, Unix programmers have been storing
function pointers in void*'s for years. I'd even be so bold as to
suggest that any compiler that didn't suppport this idiom on a Unix
system where code and data pointers are the same size would be a
failure. At the end of the day, it's more important to have code that
works than to be hypothetically pure.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
Jan 12 '07 #14
Pete Becker wrote:
Despite all these dire threats, Unix programmers have been storing
function pointers in void*'s for years.
An many unix or non unix programs have failed to work when compiled on
different machines or compilers for decades. Maybe there are some
correlation...

--
Salu2
Jan 12 '07 #15
Greg <gr****@pacbell.netwrote:
Function-to-object pointer conversions have been added to standard C++
as a "conditionally supported" conversion using reinterpret_cast<>:

"Converting a pointer to a function into a pointer to an object type or
vice versa is conditionally-supported. The meaning of such a conversion
is implementation defined, except that if an implementation supports
conversions in both directions, converting an rvalue of one type to the
other type and back, possibly with different cv-qualification, shall
yield the original pointer value." [expr.reinterpret.cast/8]
Interesting, thanks.
Conditionally-supported behavior is one that an implementation is not
required to support. But an implementation does support the feature
must then implement the feature as specified.
Is there a consolidated list of other "conditionally-supported"
features?

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
Jan 12 '07 #16
Julián Albo wrote:
Pete Becker wrote:
>Despite all these dire threats, Unix programmers have been storing
function pointers in void*'s for years.

An many unix or non unix programs have failed to work when compiled on
different machines or compilers for decades. Maybe there are some
correlation...
Sigh. More FUD.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
Jan 12 '07 #17

Pete Becker wrote:
Gavin Deane wrote:
Peter Olcott wrote:
I don't have to get my system working in theory, I have to get it working in
practice. If it does not work in theory yet does work in practice, then the
theory is discarded.
The problem you create for yourself when you take this approach is that
you have no way of knowing for how long your solution will continue to
work in practice. Examining the generated assembly language is a valid
way of checking that the behaviour in practice of your code is what you
want when the behaviour in theory is formally undefined. However,
unless your compiler documents the behaviour in practice as an
extension (which it may well do), you have no way of knowing how stable
the behaviour in practice is in the face of changes, such as compiler
options, debug vs release build, or a change in the code itself. Your
code is potentially very brittle. Every time you change something and
recompile, you have to reexamine the generated assembly language to see
if you still have the behaviour in practice that you need.

Only you know how likely such changes and the associated need to
recompile are, so only you are in a position to assess the relative
costs of losing robustness in the code vs. redesigning to avoid the
problem in the first place. But it is an assessment you must make.

Despite all these dire threats, Unix programmers have been storing
function pointers in void*'s for years. I'd even be so bold as to
suggest that any compiler that didn't suppport this idiom on a Unix
system where code and data pointers are the same size would be a
failure. At the end of the day, it's more important to have code that
works than to be hypothetically pure.
Clearly, code that doesn't work is no use. If such code is formally
correct and, according to the standard should work, you have a QoI
issue, unless your compiler documents its intended deviation from the
standard.

It is important that code works. Often (very often in my personal
experience), it is also important that the code continues to work in
the face of changes. Unless you have an inside line to the people who
make your compiler, the language standard and your compiler's
documentation of any omissions, extensions or variations from the
language standard are your only means of knowing how the compiler
manufacturer intends any C++ code to behave after their compiler has
compiled it. If you step outside that, you're on your own, flying
blind. As an engineer, stepping outside the manufacturer's
specification should be a big decision.

Gavin Deane

Jan 12 '07 #18
Gavin Deane wrote:
Pete Becker wrote:
>Gavin Deane wrote:
>>Peter Olcott wrote:
I don't have to get my system working in theory, I have to get it working in
practice. If it does not work in theory yet does work in practice, then the
theory is discarded.
The problem you create for yourself when you take this approach is that
you have no way of knowing for how long your solution will continue to
work in practice. Examining the generated assembly language is a valid
way of checking that the behaviour in practice of your code is what you
want when the behaviour in theory is formally undefined. However,
unless your compiler documents the behaviour in practice as an
extension (which it may well do), you have no way of knowing how stable
the behaviour in practice is in the face of changes, such as compiler
options, debug vs release build, or a change in the code itself. Your
code is potentially very brittle. Every time you change something and
recompile, you have to reexamine the generated assembly language to see
if you still have the behaviour in practice that you need.

Only you know how likely such changes and the associated need to
recompile are, so only you are in a position to assess the relative
costs of losing robustness in the code vs. redesigning to avoid the
problem in the first place. But it is an assessment you must make.
Despite all these dire threats, Unix programmers have been storing
function pointers in void*'s for years. I'd even be so bold as to
suggest that any compiler that didn't suppport this idiom on a Unix
system where code and data pointers are the same size would be a
failure. At the end of the day, it's more important to have code that
works than to be hypothetically pure.

Clearly, code that doesn't work is no use. If such code is formally
correct and, according to the standard should work, you have a QoI
issue, unless your compiler documents its intended deviation from the
standard.

It is important that code works. Often (very often in my personal
experience), it is also important that the code continues to work in
the face of changes. Unless you have an inside line to the people who
make your compiler, the language standard and your compiler's
documentation of any omissions, extensions or variations from the
language standard are your only means of knowing how the compiler
manufacturer intends any C++ code to behave after their compiler has
compiled it. If you step outside that, you're on your own, flying
blind. As an engineer, stepping outside the manufacturer's
specification should be a big decision.
You're welcome to spend as much time as you like seeking purity. I'll
trust Unix compilers to continue support standard idioms such as storing
function addresses in void*'s, and I'll have robust, working code long
before you do.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
Jan 12 '07 #19
Pete Becker wrote:
You're welcome to spend as much time as you like seeking purity. I'll
trust Unix compilers to continue support standard idioms such as storing
function addresses in void*'s, and I'll have robust, working code long
before you do.
Did you have? Looks like you are asking for advice because you haven't.

--
Salu2
Jan 12 '07 #20
Julián Albo wrote:
Did you have? Looks like you are asking for advice because you haven't.
Sorry, I make a mistake between your name and the OP.

--
Salu2
Jan 12 '07 #21
Julián Albo wrote:
Julián Albo wrote:
>Did you have? Looks like you are asking for advice because you haven't.

Sorry, I make a mistake between your name and the OP.
I hate when I do that.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
Jan 12 '07 #22

Pete Becker wrote:
Gavin Deane wrote:
Clearly, code that doesn't work is no use. If such code is formally
correct and, according to the standard should work, you have a QoI
issue, unless your compiler documents its intended deviation from the
standard.

It is important that code works. Often (very often in my personal
experience), it is also important that the code continues to work in
the face of changes. Unless you have an inside line to the people who
make your compiler, the language standard and your compiler's
documentation of any omissions, extensions or variations from the
language standard are your only means of knowing how the compiler
manufacturer intends any C++ code to behave after their compiler has
compiled it. If you step outside that, you're on your own, flying
blind. As an engineer, stepping outside the manufacturer's
specification should be a big decision.

You're welcome to spend as much time as you like seeking purity. I'll
trust Unix compilers to continue support standard idioms such as storing
function addresses in void*'s, and I'll have robust, working code long
before you do.
Something must be giving you the confidence to regard that as a
standard idiom that will benefit from continuing support. It's not the
language standard. Is it the compiler documentation? I hope I was clear
in my point that I regard compiler documentation of non-standard
behaviour an equally valid source of such confidence as the standard
itself.

If it's not the compiler documentation, it must be something else.
Perhaps simply an unwritten understanding amongst Unix compiler writers
that their customers expect and rely on this behaviour. If so, would it
not be better for the compiler to document the behaviour, so that the
unwritten becomes written and those new to Unix programming don't have
to learn the folklore by word of mouth?

Gavin Deane

Jan 12 '07 #23
* Gavin Deane:
Pete Becker wrote:
>You're welcome to spend as much time as you like seeking purity. I'll
trust Unix compilers to continue support standard idioms such as storing
function addresses in void*'s, and I'll have robust, working code long
before you do.

Something must be giving you the confidence to regard that as a
standard idiom that will benefit from continuing support. It's not the
language standard. Is it the compiler documentation? I hope I was clear
in my point that I regard compiler documentation of non-standard
behaviour an equally valid source of such confidence as the standard
itself.
Presumably Pete is referring to any reliable system documentation
whatsoever, such as (1) compiler documentation, and/or (2) the Posix
standard.

There is a difference between 100% portable standard C++ code and
in-practice C++ code.

One difference is, of course <g>, that in 100% portable C++ code you
can't do any i/o, since some systems have no i/o devices compatible with
the forms of i/o supported by the standard library... So there's really
not very much that can be done in 100% portable C++. Even "Hello,
world!" is not 100% portable: it requires a system with text display.
So the question is always (although unfortunately most often left
unstated): what is the range of systems that this code is meant to be
portable to? When that range is "Posix-compliant systems", storing
function pointers in void* is perfectly OK, as far as I know.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jan 12 '07 #24

Alf P. Steinbach wrote:
* Gavin Deane:
Pete Becker wrote:
You're welcome to spend as much time as you like seeking purity. I'll
trust Unix compilers to continue support standard idioms such as storing
function addresses in void*'s, and I'll have robust, working code long
before you do.
Something must be giving you the confidence to regard that as a
standard idiom that will benefit from continuing support. It's not the
language standard. Is it the compiler documentation? I hope I was clear
in my point that I regard compiler documentation of non-standard
behaviour an equally valid source of such confidence as the standard
itself.

Presumably Pete is referring to any reliable system documentation
whatsoever, such as (1) compiler documentation, and/or (2) the Posix
standard.
I'm not very familiar with the Posix standard, but if it requires
certain behaviour of C++ programs (e.g. function pointers to be
storable in void*), and the compiler documentation states something to
the effect that "this compiler implements all behaviour required by the
Posix standard" then clearly that is just as good. You know the
compiler author intends for function pointers to be storable in void*
and you know that if you write such code only a compiler bug can cause
it not to work.
There is a difference between 100% portable standard C++ code and
in-practice C++ code.
While I recognise that portability is often the reason for the kind of
argument I'm making, note that I haven't mentioned portability at all
in this thread.
One difference is, of course <g>, that in 100% portable C++ code you
can't do any i/o, since some systems have no i/o devices compatible with
the forms of i/o supported by the standard library... So there's really
not very much that can be done in 100% portable C++. Even "Hello,
world!" is not 100% portable: it requires a system with text display.
So the question is always (although unfortunately most often left
unstated): what is the range of systems that this code is meant to be
portable to? When that range is "Posix-compliant systems", storing
function pointers in void* is perfectly OK, as far as I know.
I agree with all that, however I'm not actually coming from the point
of view of portability at all. If the question is "what is the range of
systems that this code is meant to be portable to?", even if the answer
is "none at all, the code will only ever run on the current system", I
still believe is simply good engineering practice that all the code you
write relies only on behaviour documented (either directly or by
reference to another source) by the compiler author.

Gavin Deane

Jan 13 '07 #25
"Alf P. Steinbach" <al***@start.nowrote in
news:50*************@mid.individual.net:
* Gavin Deane:
>Pete Becker wrote:
>>You're welcome to spend as much time as you like seeking purity.
I'll trust Unix compilers to continue support standard idioms such
as storing function addresses in void*'s, and I'll have robust,
working code long before you do.

Something must be giving you the confidence to regard that as a
standard idiom that will benefit from continuing support. It's not
the language standard. Is it the compiler documentation? I hope I was
clear in my point that I regard compiler documentation of
non-standard behaviour an equally valid source of such confidence as
the standard itself.

Presumably Pete is referring to any reliable system documentation
whatsoever, such as (1) compiler documentation, and/or (2) the Posix
standard.

There is a difference between 100% portable standard C++ code and
in-practice C++ code.

One difference is, of course <g>, that in 100% portable C++ code you
can't do any i/o, since some systems have no i/o devices compatible
with the forms of i/o supported by the standard library... So there's
really not very much that can be done in 100% portable C++. Even
"Hello, world!" is not 100% portable: it requires a system with text
display. So the question is always (although unfortunately most often
left unstated): what is the range of systems that this code is meant
to be portable to? When that range is "Posix-compliant systems",
storing function pointers in void* is perfectly OK, as far as I know.
Well... arguably it (Hello World) is 100% portable C++ (for a hosted
environment). It is only using facilities provided by the Standard
Library. It puts "Hello, world!" into some sort of output sink. Wherever
the host decides to put that output is up to the OS & platform (Output to a
serial line, output to a screen, output to a printer, or perhaps output to
the proverbial bit bucket. In any case, it goes _somewhere_.).
Jan 13 '07 #26
Alf P. Steinbach wrote:
>
There is a difference between 100% portable standard C++ code and
in-practice C++ code.
And note that 100% standard C++ code is not ipso facto portable.
Compilers aren't perfect. Portability is a real-world concept, not a
theoretical one.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
Jan 13 '07 #27
Marcus Kwok wrote:
Greg <gr****@pacbell.netwrote:
Function-to-object pointer conversions have been added to standard C++
as a "conditionally supported" conversion using reinterpret_cast<>:

"Converting a pointer to a function into a pointer to an object type or
vice versa is conditionally-supported. The meaning of such a conversion
is implementation defined, except that if an implementation supports
conversions in both directions, converting an rvalue of one type to the
other type and back, possibly with different cv-qualification, shall
yield the original pointer value." [expr.reinterpret.cast/8]

Interesting, thanks.
Conditionally-supported behavior is one that an implementation is not
required to support. But an implementation does support the feature
must then implement the feature as specified.

Is there a consolidated list of other "conditionally-supported"
features?
Not that I know of, so I tried putting together a list myself. Aside
from the pointer-to-object opointer-to-function conversion, the other
conditionally-supported behaviors that I found, are:

A character escaped with a backslash:
"Escape sequences in which the character following the backslash is not
listed in Table 6 are conditionally-supported, with
implementation-defined semantics"
A non-POD type parameter in variable argument list:
"Passing an argument of non-POD class type (clause 9) with no
corresponding parameter is conditionally-supported, with
implementation-defined semantics."
The "asm" directive:
"The asm declaration is conditionally-supported; its meaning is
implementation-defined."
Templates with non-C, non-C++ language linkage
"A template, a template explicit specialization (14.7.3), and a class
template partial specialization shall not have C linkage. Use of a
linkage specification other than C or C++ with any of these constructs
is conditionally-supported, with implementation-defined semantics"

Not the most exciting list of features, I would admit. Perhaps
"conditionally-supported" should mean that an implementation has to
support the feature only if someone notices that the feature is
missing.

Greg

Jan 13 '07 #28
Greg <gr****@pacbell.netwrote:
Marcus Kwok wrote:
>Greg <gr****@pacbell.netwrote:
Conditionally-supported behavior is one that an implementation is not
required to support. But an implementation does support the feature
must then implement the feature as specified.

Is there a consolidated list of other "conditionally-supported"
features?

Not that I know of, so I tried putting together a list myself. Aside
from the pointer-to-object opointer-to-function conversion, the other
conditionally-supported behaviors that I found, are:

A character escaped with a backslash:

A non-POD type parameter in variable argument list:

The "asm" directive:

Templates with non-C, non-C++ language linkage

Not the most exciting list of features, I would admit.
I agree, but thanks anyway :)

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
Jan 18 '07 #29

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

10
by: Dirk Vanhaute | last post by:
I have only small knowledge of c++, but I would like to compile the example in http://support.microsoft.com/kb/q246772/ HOWTO: Retrieve and Set the Default Printer in Windows I included "#include...
4
by: Alfonso Morra | last post by:
I have come accross some code where function pointers are being cast from one type to another (admittedly, they all have the same return type). eg. you may have func ptrs declr as ff: typedef...
3
by: Alfonso Morra | last post by:
Hi, I have two func ptr prototypes declared as : typedef void (*VFP)(void) ; typedef int(MyCallback*)(enum_1, enum2, int, void*) ; I hav a struct as ff: typedef struct {
7
by: Nudge | last post by:
Hello everyone, Does the following code invoke undefined behavior? In other words, is it dangerous to lie to the compiler about a function's return type, when the return type is the same size...
3
by: Beta What | last post by:
Hello, I have a question about casting a function pointer. Say I want to make a generic module (say some ADT implementation) that requires a function pointer from the 'actual/other modules'...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.