Is it legal code?

P

Paul

itaj sherman said:
That's true.

It's not true, The pointer must be a pointer to an object. See my other
post.
I'd think Paul meant code "with defined behaviour", not just "well
formed".
But then again, he didn't specify that clearly.
And as you mention in your previous post, he doesn't seem strict about
the difference between "defined" and "defined behaviour".
When we enter the realm of calling nonstatic member functions without
objects ,the whole thing becomes generally undefined at that point.
And his response to that certainly didn't clear that up:


Does Paul mean "undefined behaviour"?

Look ^^^^^^^^^^^^^^^^^^^^^^^
Again, does Paul mean "undefined behaviour"?
The standard is worded such that a nonstatic member function must be called
on an object.
Any attempt to invoke the function without an object is not defined in the
standard.

I think it is both undefined by the standard, and also has undefined
behaviour.
 
I

itaj sherman

It's not true, The pointer must be a pointer to an object. See my other
post.


When we enter the realm of calling nonstatic member functions without
objects ,the whole thing becomes generally undefined at that point.

It is undefined behaviour.
Nothing else becomes undefind, nor "generally undefined".
Look ^^^^^^^^^^^^^^^^^^^^^^^


The standard is worded such that a nonstatic member function must be called
on an object.
Any attempt to invoke the function without an object is not defined in the
standard.

I think it is both undefined by the standard, and also has undefined
behaviour.- Hide quoted text -

The question is not whether it is "by the standard" or not.
We're all talking about the standard.
The question is whether you were referring to undefined behaviour
(stress behaviour), or anything else which you should specify.

itaj
 
P

Paul

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

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.
The standard clearly states the expression will be *pointer to* class
object.(note: this does mean pointer of type: pointer to class object)


Point out exactly where the standard is violated in either of those two
compilation units.
I just did above.
The fact that it's compiled in seperate TU's makes no difference.
 
P

Paul

itaj sherman said:
It is undefined behaviour.
Nothing else becomes undefind, nor "generally undefined".


The question is not whether it is "by the standard" or not.
We're all talking about the standard.
The question is whether you were referring to undefined behaviour
(stress behaviour), or anything else which you should specify.
As I said I think it's undefined (meaning undefined by the standard, not
that the function definiton doesn't exist).
It is generally undefined , as per above, so I also mean that it would
produce undefined behaviour.
 
I

Ian Collins

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

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(); }

Ah, but how is the authour of f to know someone will pass in NULL?
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.

But type of the the expression is a pointer to an A. It might not point
to a valid object at run time, but the code, as compiled is fine.
When you invoke a->foo() and 'a' points to 00000000 you program becomes
invalid.

No, it's behaviour is undefined.
The standard clearly states the expression will be *pointer to* class
object.(note: this does mean pointer of type: pointer to class object)

No, it states the *type* (emphasis mine) of pointer expression shall be
“pointer to class object”. Not the value shall be “pointer to an
instance of a class object”. The difference is important. Remember,
member functions belong to the class, not the instances of it.
I just did above.
The fact that it's compiled in seperate TU's makes no difference.

Oh but it does, both are perfectly legal, standard C++.
 
P

Paul

itaj sherman said:
Yeah. That's what I meant.
That I think it is beneficial to think of nonstatic member functions
this way. for example:
void A::foo( Par1, Par2 );
as a function of arity 2, with a first parameter of type A&, that is
special in the following properties:
- in the call syntax it is written before the function arg0.foo( arg1,
arg2 )
- the lookup for the function name is done only by that special
argument's type, and not by all the other (unlike global functions).
So the difference with global functions or static member function is
only in the call syntax and lookup rules, but nothing else.
* Except for that weird temporary bind to non-const reference
difference. I think they probabely should all been disallowed.

That is, such a function is equivalent to:
void foo( A&, Par1, Par2 );
foo( arg0, arg1, arg2 );

I think keeping in mind this equivalence would be beneficial for your
subjects of arguments' validity and any definition of existance.


I'm not sure what you mean by "calling conventions".
What I was thinking along the lines of passing arguments left to right and
others right to left , on stack or in register. Stuff like that.
However, the virtual case is more delicate to express but is not
different. There's still no inherent difference with global functions,
because:
In theory virtuality is a property of any certain parameter of a
function. I.e a few parameters of a certain function can be virtual -
such functions are called "multimethods". And again, theoretically it
does not matter if they are global, static members or nonstatic
members (that just changes the syntax). There are languages that have
this feature.
Although Stroustrup wanted to add this feature to c++ already before
1990, as he says in "The Design and Evolution of C++", the main reason
we don't have them in c++ by now, is not enough time to work on that,
due to other more important features they had to add.
I do believe it will be added one day to the language, though
probabely not even by c++1X.
This is a quite complicated feature to implement for a language. It
has been decided to restrict the virtuality feature in a way that
allows implementation of it to be much simpler, and that required:
- only 1 parameter of a function is allowed to be virtual
- any override of a function that is virtual on a certain parameter,
must be declared within the class type of this parameter. practically
then, it was very convenient to call them "virtual member functions",
and use the same syntax rules as nonstatic member functions.
And when we need multi-virtuality we use workaround idioms like multi-
dispatch.

For example, the multi-virtuality feature could look like:

class Carnivour {};
class Prey{};
void eat_prey( virtual Carnivour&, virtual Prey& ) = 0;

//overrides
class Lion: public Carnivour {};
class Anaconda: public Carnivour {};
class Bear: public Carnivour {};

class Girrafe: public Prey {};
class Gazelle: public Prey {};

void catch_prey( Lion&, Gazelle& ) { ... } //jumps on it and bite its
neck
void catch_prey( Lion&, Girrafe& ) { ... } //bite its ass
void catch_prey( Cobra&, Gazelle& ) { ... } //inject venom
//Anaconda can't kill girrafes so no override for that one
void catch_prey( Bear&, Prey& ) { ... } //because Bears catch
everything in the same way lol.
I will need to study your virtual functions scenario at a later date, I am
still trying to grasp your non virtual function way of thinking :)
I didn't say that it exists.
I say: if we define the meaning of "function exists" in a certain way,
then it should turn out the same for nonstatic member function as for
any reference parameter in any type of function.
But I don't know any definition for "function exists" and I don't know
what beneficial usage could be done with such definition.
One term I have seen is 'member function instance' or 'instance of member
function'. I don't like that term because, to me, it seems to suggest a copy
is created.
 
P

Paul

Johannes Schaub (litb) said:
For some objects, they exist not only during their lifetime, but also
afterwards and previously: The lifetime of class objects start as soon as
their constructor finishes execution, and their lifetime stop as soon as
the destructor begins execution. But the object already exists at the
start of the constructor execution and still exists until the destructor
stops execution.

The Standard is not actually clear about the existence-question of
objects,
I think. I think you can say that for non-class objects, their lifetime
defines their existence. But for class objects, the definition is more
complicated. An alternative model I can see can be interpreted from the
Standard is that an object starts existence independently from starting
its
lifetime. But this alternative model has serious trouble, including the
question how objects that are created by mere writes to storage (malloc +
write) come to existence.
Yep it all seems to get a bit nitpicky when you get down to the nittygritty
milliseconds of when its actually created and stuff.
Thanks for the post.
 
P

Paul

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

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(); }

Ah, but how is the authour of f to know someone will pass in NULL?
I dunno its your code, maybe:
if(a)a->foo();
But type of the the expression is a pointer to an A. It might not point
to a valid object at run time, but the code, as compiled is fine.
It's not the type that is in question , its what it points to.
I doesn't point to a valid object because your code passes it a NULL.
No, it's behaviour is undefined.
It's breaking the rules defined in the C++ standard, and it will crash and
burn.
>

No, it states the *type* (emphasis mine) of pointer expression shall be
“pointer to class object”. Not the value shall be “pointer to an instance
of a class object”.
Don't be silly , how can a type point to anything.
Your being unreasonable here , the standards simply do not state that at
all, I'm not even gonna bother requoting to prove it , its further up the
page, I quoted it plenty already.
The difference is important.
Yes exactly it was me who initially pointed it out.
Remember, member functions belong to the class, not the instances of it.

Thats not what I remember. I remember static member functions belong to a
class, and nonstatic member functions belong to an object.
Oh but it does, both are perfectly legal, standard C++.
Just because it compiles doesn't make it a valid program.
 
I

Ian Collins

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

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(); }

Ah, but how is the authour of f to know someone will pass in NULL?
I dunno its your code, maybe:
if(a)a->foo();

So there's nothing wrong with f? Good.
It's not the type that is in question , its what it points to.
I doesn't point to a valid object because your code passes it a NULL.

Oh but it is, it was you who brought up 5.2.5.
It's breaking the rules defined in the C++ standard, and it will crash
and burn.

So be it, but the code didn't contain any constraint violations, so it
(the code) was standard compliant.
Don't be silly , how can a type point to anything.

I'm not being silly, I was pointing out an error in your interpretation
of 5.2.5 (with the actual text).
Your being unreasonable here , the standards simply do not state that at
all, I'm not even gonna bother requoting to prove it , its further up
the page, I quoted it plenty already.

I quoted it for you, and I'll quote it again:

"the first expression (the pointer expression) shall be "pointer to
class object" (of a complete type)."

No mention of value, just types.
Yes exactly it was me who initially pointed it out.


Thats not what I remember. I remember static member functions belong to
a class, and nonstatic member functions belong to an object.
Just because it compiles doesn't make it a valid program.

You asked for "standard compliant code" and you have yet to show how the
code violates any constraints.
 
G

gwowen

One term I have seen is 'member function instance' or 'instance of member
function'. I don't like that term because, to me, it seems to suggest a copy
is created.

struct foo {
int p;
public:
p() : p(0) {};
int getp() const {return p;}
};

int main()
{
std::cout << &foo::getp;
}

No objects of class foo are created. The address of the member
function is correctly resolved. I could even pass it as a member-
function pointer to a routine that would call it on some "foos" to-be-
created-later. That would suggest that from the compilers point of
view, its existence is pretty unambiguous.
 
I

itaj sherman

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

When did anyone said it does? Demonstrate his quote please.
I quoted it for you, and I'll quote it again:

"the first expression (the pointer expression) shall be "pointer to
class object" (of a complete type)."

You should quote the few words before that, as you did earlier:

the type of the first expression (the pointer expression) shall
be “pointer to class object” (of a complete type)

It begins with "the type of...". Doesn't it make your point very
clear?
No mention of value, just types.

itaj
 
I

itaj sherman

Just because it compiles doesn't make it a valid program

What you mean by valid?
Whether this progeam is not well formed or just has undefined
behaviour, how does it affect your questions?

itaj
 
P

Paul

One term I have seen is 'member function instance' or 'instance of member
function'. I don't like that term because, to me, it seems to suggest a
copy
is created.

struct foo {
int p;
public:
p() : p(0) {};
int getp() const {return p;}
};

int main()
{
std::cout << &foo::getp;
}

No objects of class foo are created. The address of the member
function is correctly resolved. I could even pass it as a member-
function pointer to a routine that would call it on some "foos" to-be-
created-later. That would suggest that from the compilers point of
view, its existence is pretty unambiguous.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

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;
 
P

Paul

I'm not being silly, I was pointing out an error in your interpretation of
5.2.5 (with the actual text).

I have to admit it does say type , but this misunderstanding is due to your
innapporiopriate snipping of my original quote.
However this does not make your program valid, that was only one of many
arguments I have against your program.


You asked for "standard compliant code" and you have yet to show how the
code violates any constraints.

You produce UB prior to invokation of the member function, to suggest that
the results of UB is standard compliant code is nonsense.
 
P

Paul

Just because it compiles doesn't make it a valid program

What you mean by valid?
Whether this progeam is not well formed or just has undefined
behaviour, how does it affect your questions?

......................................................................................

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.
 
J

James Kanze

On 20/02/2011 15:15, James Kanze wrote:

[...]
They don't exist in the sense that they are all converted to machine
code that lives in the text segment; all that is left to indicate their
existance are references to their start addresses (assuming we are not
talking about the inlining case).

Functions don't "exist" (with regards to the standard), in that
they are not objects, and do not have a lifetime. They do exist
in the sense that you can take their address. The whole issue
is more metaphysical than anything else---what does it mean for
a function to "exist".

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.

But in the end, who cares? The whole discussion sounds more
like metaphysics than anything useful. Pragmatically, if you
want to communicate, you use the same vocabulary as everyone
else, even if you think it less than ideal. And if you don't
want to communicate, why bother posting at all?
 
J

James Kanze

You must've forgot we are talking about *member functions*.

So what's the difference, with regards to your argument.
An object(instance of a class type) has a lifetime, it exists
for the duration of its lifetime. Because C++ disallows
calling nonstatic member functions, without an object of , or
derived from, the respective class type. A non static member
function cannot exist unless an object exists.

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.
 
P

Paul

James Kanze said:
On 20/02/2011 15:15, James Kanze wrote:
[...]
It follows that if an object(or derived object) does not
exist then it is undefined behaviour to call its respective
nonstatic member function? Therefore it must be true that
a member function does not exist without an object.
I don't quite follow you here. If I have a function:
void f(int&);
, it's undefined behavior for me to call f without a an object
of type int. The function f(int&) still "exists". For some
definition of "exists"---this is getting a bit too metaphysical
for me. One could argue that in C++, only "objects" exist, and
references and functions aren't objects, so can't "exist".
They don't exist in the sense that they are all converted to machine
code that lives in the text segment; all that is left to indicate their
existance are references to their start addresses (assuming we are not
talking about the inlining case).

Functions don't "exist" (with regards to the standard), in that
they are not objects, and do not have a lifetime. They do exist
in the sense that you can take their address. The whole issue
is more metaphysical than anything else---what does it mean for
a function to "exist".

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.

But in the end, who cares?
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 proffessional.
The whole discussion sounds more
like metaphysics than anything useful. Pragmatically, if you
want to communicate, you use the same vocabulary as everyone
else, even if you think it less than ideal. And if you don't
want to communicate, why bother posting at all?

People around here keep thinking they speak for the majority but this is not
the case.

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.
 
J

James Kanze

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. (Interestingly enough, one can also take the
"address" of a data member, independently of the existance of an
object.)
 

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

Staff online

Members online

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,040
Latest member
papereejit

Latest Threads

Top