Is it legal code?

G

Gerhard Fiedler

Paul said:
I think your constructor should be named foo, a typo probably.

I don't know what you try to say when you say the address is
correctly resolved but your code demonstrates the same as this:

int x=0;
std::cout << &x;

Also. But in the context of this thread it also shows that the function
exists (for at least one quite reasonable definition of "exists")
independently of any object of the class foo.

Gerhard
 
P

Paul

James Kanze said:
So what's the difference, with regards to your argument.
The difference is that the standard defines a rule for nonstatic member
functions. The same rule does not apply to normal functions.
What does the ability to call a function have to do with its
existance? To call a function (any function), you have to have
objects which correspond to its parameters, or at least to those
parameters which require lvalues. If "existance" of a function
has any meaning related to execution, then the only reasonable
definition for "exists" is "has an address which can be taken";
addresses determine, for example, whether we have one object or
two. And you can take the address of any function (member or
non-member) at any time during execution, regardless of what
objects may or may not exist.
Because the function was declared as a member of an object-type, if you
directly invoke this function without an object you'll produce UB.

When considering the existence of a NSMF, you must take into account the
object on which it was called.
For example consider two different objects both processing the same member
function, at exactly the same time. Its the same function definition for
each NSMF but its certainly not the same function that's executing.
I understand your POV with the basic old mathematical function concept i.e:
input --> function process --> output., that all function are more or less
handled the same for a given architecgture/calling convention. To clairfy
what i mean is the register/stack state is almost identical for each
function invocation, the only thing that changes may be a few variable
values.
But when we look at NSMF's then things become a little bit different and
addressing and such becomes a little more complex vtables etc. Imagine two
different objects invoking their same respective NSMF's simultaneously, each
is a completely different process. Thus when speaking of NSMF's I think it
is a valid concept that the existence of the function starts when invoked
and ends on return.

ALso the implementation is not bound to implement the mechanics in any
defined way. So addressing and such is very imp-specfic.
As an example: In some cases it may be more optimal for an implementation to
have 2 versions of the same function, or something like this.
 
P

Paul

Gerhard Fiedler said:
Also. But in the context of this thread it also shows that the function
exists (for at least one quite reasonable definition of "exists")
independently of any object of the class foo.
As the function has been defined(as in function defintion), its function
definition exists someplace in memory.
However the function was declared to be a member of an object-type. It is UB
to invoke it without an object.
I don't disagree that it is technically possible to invoke the function
without an object, but rules of C++ is that it'll produce UB.

A program that produces UB is no longer a valid C++ program unless the UB is
defined by the implementation.
So if you can find a implementation with documentation that defines the
behaviour, you have a valid argument. Otheriwse its not a valid C++ program
IMO.
( I have really reaserched the standard thoroughly on what the exact rules
are about implementations defining their own behaviour but I think this is a
pretty fair guess at the rules, I may be incorrect).


The whole function existence argument is going on elsethread.
TY for post.
 
P

Paul

Leigh Johnston said:
Ian Collins said:
On 02/21/11 02:14 PM, Paul wrote:

On 02/21/11 12:05 PM, itaj sherman wrote:
On 02/21/11 11:11 AM, Paul wrote:


Can he actually show some standard compliant code that calls a
nonstatic
member function
a) on a class type
b) without and object.

a.h:

struct A { void foo(); };

void f( A* a );

a.cc:

#include "a.h"

void A::foo() {}

void f( A* a ) { a->foo(); }

main.cc:

#include "a.h"

int main()
{
A a;

f(&a); // With object.
f(NULL); // Without object.

I think this is undefined behaviour, even thought A::foo is empty.
inside f(),
a->foo()
is equivalent to:
(*a).foo()
which would be an indirection of NULL, undefined behaviour.
isn't it?

It may result in undefined behaviour, but there's nothing non standard
in the code. I put the declaration and definition in separate
compilation units to force the point. There is no way the compiler can
know about the working of f() when compiling main.cc.


No the code is invalid ref:
"5.2.5 Class member access [expr.ref]

<snip>

The above quote from the C++ standard states "the first expression (the
pointer expression) shall
be "pointer to class object" (of a complete type). ".
Your expression a->foo() , with a =NULL, is not valid C++ code.

Where did I write a->foo() , with a =NULL?

f(NULL) /*passes NULL to*/
void f( A* a ) { a->foo(); }
I wrote a->foo() with a being an A* which is a pointer to a complete
type.

Your expression is not a pointer to an A. The pointer *type* is pointer
to A, this doesn't mean it points to an A.

When you invoke a->foo() and 'a' points to 00000000 you program becomes
invalid.

A null pointer does not have to have a value of 0 (it has an
implementation-defined bit pattern);

What other value can a NULL pointer have?
i.e. a pointer can have a value of 0 and still be valid:
Yes a null pointer is a valid entity but this doesn't cohere with ..... "a
null pointer doesn't have to have a value 0".

char* p = (char*) 1;
--p; // on some systems p could still be valid (0)
I guess it could :)
 
P

Paul

James Kanze said:
On 20/02/2011 21:44, Paul wrote:
[...]
In C++ a member function is a member of a class not a member of an
object; in C++ an object is simply a region of storage; in C++ a
non-static member function is *invoked* on an object it is not part of
an object.

In C++, an object is a *contiguous* region of storage. Each
object has a distinct address.

C++ also requires pointer to member functions to compare equal
if they point to the same function. So member functions cannot
be members of an object; they must have an existance outside of
the object.
They do have an existence outside objects, but their existence outwith an
object is undefined.

This doesn't mean they are not members of an object but members of a class,
they don't exist inside a class either. The class doesn't even exist
anymore, its as precompile time entity.
The class-type or object-type( means the same thing) , is defined. If this
type is defined to have a NSMF then the NSMF is a member of the object and
the class-type.

*It's not simply a class member because this terminology is used to mean
static members*.
(Interestingly enough, one can also take the
"address" of a data member, independently of the existance of an
object.)
There you go , that just explains how crazy it is to try and use object
members without an object.
 
P

Paul

Leigh Johnston said:
Leigh Johnston said:
On 21/02/2011 02:32, Paul wrote:

On 02/21/11 02:14 PM, Paul wrote:

On 02/21/11 12:05 PM, itaj sherman wrote:
On 02/21/11 11:11 AM, Paul wrote:


Can he actually show some standard compliant code that calls a
nonstatic
member function
a) on a class type
b) without and object.

a.h:

struct A { void foo(); };

void f( A* a );

a.cc:

#include "a.h"

void A::foo() {}

void f( A* a ) { a->foo(); }

main.cc:

#include "a.h"

int main()
{
A a;

f(&a); // With object.
f(NULL); // Without object.

I think this is undefined behaviour, even thought A::foo is empty.
inside f(),
a->foo()
is equivalent to:
(*a).foo()
which would be an indirection of NULL, undefined behaviour.
isn't it?

It may result in undefined behaviour, but there's nothing non
standard
in the code. I put the declaration and definition in separate
compilation units to force the point. There is no way the compiler
can
know about the working of f() when compiling main.cc.


No the code is invalid ref:
"5.2.5 Class member access [expr.ref]

<snip>

The above quote from the C++ standard states "the first expression
(the
pointer expression) shall
be "pointer to class object" (of a complete type). ".
Your expression a->foo() , with a =NULL, is not valid C++ code.

Where did I write a->foo() , with a =NULL?


f(NULL) /*passes NULL to*/
void f( A* a ) { a->foo(); }

I wrote a->foo() with a being an A* which is a pointer to a complete
type.

Your expression is not a pointer to an A. The pointer *type* is pointer
to A, this doesn't mean it points to an A.

When you invoke a->foo() and 'a' points to 00000000 you program becomes
invalid.

A null pointer does not have to have a value of 0 (it has an
implementation-defined bit pattern);

What other value can a NULL pointer have?

The correct term is "null pointer" not "NULL pointer" and I told you: an
implementation-defined bit pattern (i.e. it doesn't have to be 0).
Yes a null pointer is a valid entity but this doesn't cohere with .....
"a null pointer doesn't have to have a value 0".


I guess it could :)

You claimed that "if 'a' points to 00000000 your program becomes invalid";
this is incorrect as 0 can be a non-null pointer value on some systems.

int zero_value = 0;
char* p = (char*)zero_value; // p is not a necessarily a null pointer
You are really scraping the bottom of the nitpicking barrel now.

A null pointer to me is:
char* p_char=0;

I there is some fancy new way to do this, then I admit I don't know anything
about it.
IMHO a null pointer is a pointer with an address of zero, I don't know about
this implementation you speak of where null is not zero and I guess I need
to live with the fact that my code would crash and burn on such an
implementation.
 
S

Stuart Redmann

:
[snip]
If it results in undefined behaviour then there is obviously something wrong
with the code. What is valid and/or illegal code, if not code that produces
undefined behaviour ?


I always thought that the C++ standard stated what it considers
invalid code, e.g. something like

#include <iostream>
int main ()
{
int i = 0;
std::cout << ++i++;
}

is illegal code according to the C++ standard, in contrast to

#include <iostream>
int main ()
{
int* i = 0;
std::cout << *i;
}

which is undefined behaviour.

Invalid code relieves the compiler from having to handle non-sense
code, whereas UB relieves the run-time from having to handle non-sense
code.

Regards,
Stuart

PS: In my opinion the life-time of members functions and ordinary
functions should be equivalent, so I wouldn't go so far as to say that
we need at least one object in order for its member functions to
exist. I don't know whether the C++ standard agrees with me, but I
would be surprised if the authors of the standard had a different
opinion.
 
P

Paul

Stuart Redmann said:
:
[snip]
If it results in undefined behaviour then there is obviously something
wrong
with the code. What is valid and/or illegal code, if not code that
produces
undefined behaviour ?


I always thought that the C++ standard stated what it considers
invalid code, e.g. something like

#include <iostream>
int main ()
{
int i = 0;
std::cout << ++i++;
}

is illegal code according to the C++ standard, in contrast to

#include <iostream>
int main ()
{
int* i = 0;
std::cout << *i;
}

which is undefined behaviour.

Invalid code relieves the compiler from having to handle non-sense
code, whereas UB relieves the run-time from having to handle non-sense
code.
Invalid code , illformed program , illegal construct etc etc are all terms
that mean generally screwed up code.

Whatever the correct terminology the bottom line is that if a program
invokes UB, whatever happens after that is anyones guess.
So consider the following psuedo code:
do something;
do something else;
invoke UB;
do something more;

'do something more' cannot be considered part of a valid C++ program. There
is no defined sequence after the UB.


Stuart

PS: In my opinion the life-time of members functions and ordinary
functions should be equivalent, so I wouldn't go so far as to say that
we need at least one object in order for its member functions to
exist. I don't know whether the C++ standard agrees with me, but I
would be surprised if the authors of the standard had a different
opinion.
What is your idea of the lifetime of a function?
a) from function calling code until return?
b) from start of program until end of a program?
c) something other?


TY
Paul.
 
P

Paul

Leigh Johnston said:
That is a null pointer yes.


No it is not new or fancy just something that has always been the case and
you are ignorant of.


A null pointer value does not have to be zero; a null pointer value is an
address.
The above seems incorrect:
A null pointer is a pointer that *doesn't* have an address.
You need to learn the difference between "null pointer constant" and "null
pointer value". A null pointer constant (0) is converted into a null
pointer value which does not have to be 0.
TY, I will look it up ;)
 
P

Paul

Leigh Johnston said:
Functions only exist as machine code in the text segment; inlined
functions exist as machine code in the calling function in the text
segment.
Leigh stop spouting crap about machine code and segments.
a) A system can name mem segments as it chooses.
b) A function does not only exist in *THE* text segment, this is crap.
c) There is no clear definition on the lifetime/existence of functions,
please don't make claims as if it was a well-defined-fact.
 
J

James Kanze

[...]
In practice, as someone else has pointed out in this thread, you
can take the address of a non-static member function, with or
without the presense of an object. Which seems like
a conclusive argument that whatever non-static member functions
might be, and whether they exist or not, their reality or status
or whatever is independent of any object.
I have pointed this out , but I aslo pointed out this would
not be standard complaint. I disagree with your analysis,
I think the standard defines a rule that means a function
cannot exists without an object, the opposite of your
conclusion.

So what am I taking the address of, when I take its address.
Given something like:

struct Toto
{
void titi();
};

int
main()
{
void (Toto::*pmf1)() = &Toto::titi;
// What does pmf1 point to, if Toto::titi
// doesn't exit?
Toto* p1 = new Toto;
Toto* p2 = new Toto;
void (Toto::*pmf2)() = &Toto::titi;
// And what about here, since according to
// your logic, there are now two Toto::titi?
}

No matter how you cut it: if existance has any meaning for
a member function, it exists for the entire time the program
runs, regardless of the presence or absence of instances.
What kind of attitude is that? If you don't accept the rules
of the language, that's hardy good pr for you as
a professional.

What does your argumentation have to do with the rules of the
C++ language? It's purely a lexical dispute.
People around here keep thinking they speak for the majority
but this is not the case.

Except that you can't find anyone speaking differently, at least
where C++ is concerned.
Just take alook at your argument in the stl thread James , you
originally started of arguing with the majority , then later
it evolves that you don't even support that cause. You just
argued on-sdie with Pete becker etc because they seemed like
the stronger side to be on., this doesn't mean everyone
arguing against you has a failure to communicate.

In the case of the STL argument, I've argued consistently that
the term is ambiguous. Unlike the current discussion, there is
no consensus among C++ practitionners as to what STL means. In
some ways, this is regretable, but neither I nor anyone else can
force consensus. (Luckily, in the case of the meaning of STL,
the distinction isn't really important.)
 
S

Stuart Redmann

Invalid code , illformed program , illegal construct etc etc are all terms
that mean generally screwed up code.

Whatever the correct terminology the bottom line is that if a program
invokes UB, whatever happens after that is anyones guess.
So consider the following psuedo code:
do something;
do something else;
invoke UB;
do something more;

'do something more' cannot be considered part of a valid C++ program. There
is no defined sequence after the UB.

Agreed. However, there is a subtle difference between illegal code and
UB: Illegal code says that different compilers are not forced to
produce semantically equivalent machine code, whereas UB means that
different run-times may produce different results. While I consider
illegal code as something that must be avoided at all costs, I allow
for very, very few occurances of UB (for example casting a
std::vector<Derived*> to _const_ std::vector<Base*>).


Stuart Redmann said:
What is your idea of the lifetime of a function?
a) from function calling code until return?
b) from start of program until end of a program?
c) something other?

I'd opt for b).

Regards,
Stuart
 
J

James Kanze

news:7d493a8c-de14-4c84-b63a-2cfbb0cc9042@o13g2000yql.googlegroups.com...
On 20/02/2011 21:44, Paul wrote:
[...]
In C++ a member function is a member of a class not a member of an
object; in C++ an object is simply a region of storage; in C++ a
non-static member function is *invoked* on an object it is not part of
an object.
In C++, an object is a *contiguous* region of storage. Each
object has a distinct address.
C++ also requires pointer to member functions to compare equal
if they point to the same function. So member functions cannot
be members of an object; they must have an existance outside of
the object.
They do have an existence outside objects, but their existence
outwith an object is undefined.

And what does "existence [..] is undefined" mean?
This doesn't mean they are not members of an object but members of a class,
they don't exist inside a class either. The class doesn't even exist
anymore, its as precompile time entity.
The class-type or object-type( means the same thing), is defined. If this
type is defined to have a NSMF then the NSMF is a member of the object and
the class-type.

Within the C++ standard, class type and object type are two very
different concepts. A "class type" is a subset of all possible
types. An "object type" is a much larger subset: int in not
a class type, but it is an object type.

This is the usual C++ terminology.
*It's not simply a class member because this terminology is
used to mean static members*.

By whom? In what context? I've worked with a lot of C++
programmers, over the last twenty or so years, and I've never
heard one use it this way.
 
J

James Kanze

news:0e0dc254-eccb-42aa-8ab7-35db4c4218e1@w21g2000yqm.googlegroups.com...

[...]
So what's the difference, with regards to your argument.
The difference is that the standard defines a rule for nonstatic member
functions. The same rule does not apply to normal functions.

The only difference defined by the standard is that nonstatic
member functions have an implicit first parameter, of type T&
(or T const&).
Because the function was declared as a member of an
object-type, if you directly invoke this function without an
object you'll produce UB.

How is that different from calling any other function which
takes a reference without an object that the function refers to?
When considering the existence of a NSMF, you must take into account the
object on which it was called.

Why? It obeys exactly the same rules as a static member
function, or a free function.
For example consider two different objects both processing the
same member function, at exactly the same time. Its the same
function definition for each NSMF but its certainly not the
same function that's executing.

It most certainly is the same function. The standard requires
it.
I understand your POV with the basic old mathematical function concept i.e:
input --> function process --> output., that all function are more or less
handled the same for a given architecgture/calling convention. To clairfy
what i mean is the register/stack state is almost identical for each
function invocation, the only thing that changes may be a few variable
values.
But when we look at NSMF's then things become a little bit different and
addressing and such becomes a little more complex vtables etc. Imagine two
different objects invoking their same respective NSMF's simultaneously, each
is a completely different process. Thus when speaking of NSMF's I think it
is a valid concept that the existence of the function starts when invoked
and ends on return.
ALso the implementation is not bound to implement the
mechanics in any defined way. So addressing and such is very
imp-specfic. As an example: In some cases it may be more
optimal for an implementation to have 2 versions of the same
function, or something like this.

An implementation is certainly allowed to make as many copies of
the function as it wishes. Member or otherwise. On the other
hand, the standard requires that all pointers to the function
compare equal. Member or otherwise. Even if the implementation
makes many "copies" of the function (as it typically does if the
function is inline), it has to ensure that all of the pointers
to the function compare equal.

This is very close, if not identical, with the OO concept of
identity. In C++, if two addresses (of objects) compare equal,
they are the same object. Comparison of address is the way you
test identity in C++.
 
I

itaj sherman

Valid for this purpose is that........... it invokes the member function
using standard compliant code.

Once the program produces UB it becomes invalid.

UB may make your screen go green , or is may eject your CD drive, who knows.
So it's nonsense to suggest that the program is valid after this point.

Well then say UB, like the standard does, and everyone else.
If you say words I don't know like "valid" I can't be sure I
understand you.

itaj
 
P

Paul

James Kanze said:
[...]
In practice, as someone else has pointed out in this thread, you
can take the address of a non-static member function, with or
without the presense of an object. Which seems like
a conclusive argument that whatever non-static member functions
might be, and whether they exist or not, their reality or status
or whatever is independent of any object.
I have pointed this out , but I aslo pointed out this would
not be standard complaint. I disagree with your analysis,
I think the standard defines a rule that means a function
cannot exists without an object, the opposite of your
conclusion.

So what am I taking the address of, when I take its address.

You are in a gray area where you have a pointer to a functions definition,
but you can't invoke the function, so does the function exist?
Given something like:

struct Toto
{
void titi();
};

int
main()
{
void (Toto::*pmf1)() = &Toto::titi;
// What does pmf1 point to, if Toto::titi
// doesn't exit?
Its the address InstrPointer will point to when the the function is
invoked.( for an assumed machine architecture).
&Toto::titi is the location where the function is defined.
Toto* p1 = new Toto;
Toto* p2 = new Toto;
void (Toto::*pmf2)() = &Toto::titi;
// And what about here, since according to
// your logic, there are now two Toto::titi?
No there are two pointers.
Toto::titi is part of the class/object-type defiition, there is only one
definiton for all instances of this class/object-type.
(whether this is guaranteed to be the case on all implementations, I think
is undefined).

Note: I am not talking about breaking the one definition rule , I am
thinking of possible implementations of virtual functions.
}

No matter how you cut it: if existance has any meaning for
a member function, it exists for the entire time the program
runs, regardless of the presence or absence of instances.
If you are going to give a function a lifetime then consider a function as a
sub-process. What is the lifetime of that sub-process?
It seems stupid to speak about the lifetime of a function, where every
function has the same lifetime(that of program execution).
What does your argumentation have to do with the rules of the
C++ language? It's purely a lexical dispute.
The rules suggest that a NSMF cannot be called unless called on an object.
This supports my argument that C++ supports the OOP concept that NSMF's are
members of an object.

If you are suggesting C++ does not support OOP, this seems like a pretty
bold statement to make considering the overwhelming evidence to suggest
otherwise. I don't see how you can brush this of as 'purely lexical'.
Except that you can't find anyone speaking differently, at least
where C++ is concerned.
No I can find hundreds of quotes to support me, the fact that nobody in here
seems to be speaking up against the majority(in here) doesn't mean you are
the real majority.
In the case of the STL argument, I've argued consistently that
the term is ambiguous. Unlike the current discussion, there is
no consensus among C++ practitionners as to what STL means. In
some ways, this is regretable, but neither I nor anyone else can
force consensus. (Luckily, in the case of the meaning of STL,
the distinction isn't really important.)
You and a few other in here have claimed that a NSMF is a member of a class
but not an object.
You have given no evidence at all to support your claim except for the fact
that you are in the majority therefore you are correct.

C++ is a language where the class is the definition of an object, so to say
something is a member of a class but not part of an object doesn't make
sense, bar the exception of static members.

Member functions as part of an object are a well defined OOP concept and if
a language doesn't support this, it cannot be said to support OOP. However
C++ does support OOP so therefore it follows that C++ supports the concept
of member functions as members of an object. The argument you have put
forward is very non supportive of OOP, and if your argument was correct it
would mean C++ did not support OOP.

Can you at least agree that a language must support this concept to support
OOP?
 
P

Paul

James Kanze said:
news:7d493a8c-de14-4c84-b63a-2cfbb0cc9042@o13g2000yql.googlegroups.com...
On 20/02/2011 21:44, Paul wrote:
[...]
In C++ a member function is a member of a class not a member of an
object; in C++ an object is simply a region of storage; in C++ a
non-static member function is *invoked* on an object it is not part of
an object.
In C++, an object is a *contiguous* region of storage. Each
object has a distinct address.
C++ also requires pointer to member functions to compare equal
if they point to the same function. So member functions cannot
be members of an object; they must have an existance outside of
the object.
They do have an existence outside objects, but their existence
outwith an object is undefined.

And what does "existence [..] is undefined" mean?

I actually covered two things by this:
1)The existence/lifetime of a function is a gray area and is undefined.
2)When a function is invoked on an object its behaviour is defined,
otherwise it is undefined.
Within the C++ standard, class type and object type are two very
different concepts. A "class type" is a subset of all possible
types. An "object type" is a much larger subset: int in not
a class type, but it is an object type.
What you say above seems illogical to me i.e the following are incoherent.:
1) a class type is a subset of all possible types
2) object type is a larger subset, int is not a class type.

How can you get larger subset than *all possible* types?
This is the usual C++ terminology.
IMO the standards loose use of the word 'object' to mean almost anything
imaginable is confusing.
Everytime I use the word now I feel the need to follow it with a bracketed
description to define my meaning(which is normally an instance of
class-type).
..
By whom? In what context? I've worked with a lot of C++
programmers, over the last twenty or so years, and I've never
heard one use it this way.
http://en.wikipedia.org/wiki/Class_variable
:)
 
P

Paul

Leigh Johnston said:
What has that got to do with anything? "Text segment" is a well known
computer science term; "code segment" is a synonym.


When you understand what people mean by "text segment" you will see how
full of crap you have been.

I know more about segments than you.
Functions only exist as machine code in the text segment; inlined
functions exist as machine code in the calling function in the text
segment.
"A function is not an object"
A function is a sub process, it exists on the Stack and CPU registers.

Please stop making noobish statements like: "Functions only exist as machine
code in the text segment".
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top