Re: fields for methods?




On Fri, 13 Oct 2006, Jon Slaughter wrote:
"Arthur J. O'Dwyer" <ajonospam@xxxxxxxxxxxxxx> wrote...
On Fri, 13 Oct 2006, Jon Slaughter wrote:


But did you understand my "big drawback" above? I didn't explain it
very explicitly, I guess. The objection is that your idea can be
translated directly into C++, but only by a compiler that is allowed to
see all of your source code at once. You can't define 'A' in one module
and 'A::foo' in another module, and then compile each module separately
and link them together ("separate compilation", a cornerstone of the
C/C++/Unix-in-general programming model), because the definition of
'A::foo' actually adds the data field 'i' to the struct 'A', changing
the size of an 'A' object.

yes, but I'm saying that A and foo are the same thing and hence you can't
define them sep[a]rately. The language syntax makes it such that

struct A { void foo(); };

void A::foo() {
int static_instance i = 0;
printf("%d\n", i);
++i;
}

Is not possible because foo is the only member of A... so why not just call
it A? i.e.

function void A()
{
int static_instance i = 0;
printf("%d\n", i);
++i;
}

Okay, now you're changing the question, at least as far as I can tell.
You had originally, I thought, had 'foo' being a member function bound
to a particular class 'A'. Here, in this example, it looks like you
just want 'A' (previously called 'foo') to be a global function; and
if that's so, then you can just use the 'static' keyword that C++ already
provides. That'll give you an 'i' that persists between calls to 'A'.

The two codes are identical but there syntax/grammar is different. It
doesn't matter how the compiler internally reprsents "function" if it is a
struct like you have shown or makes an "anonymous" global variable i such as

int i238483288394 = 0;
void A()
{
printf("%d\n", i238483288394);
++i238483288394;
}

Right; this is how 'static' local variables are typically implemented.

but the above code is slightly different from what I want in the sense that
I do want in some way to get at the variable. Since the compiler generates
an anonymous variable(the i238483288394) at compile time theres no way to
know what it is. Instead I define it using some keyword or syntax like in
the 2nd example and reference it through the '.' (or some other method).

You haven't given any reason yet /why/ you want to get at someone
else's local variables, though. Can you give an example of a situation
in which reading other functions' static variables would be useful?
(And notice that if you're using 'foo.i' outside of function 'foo'
anyway, there's no justification for saying it's "local" to function
'foo'. You might as well make it global and have done with it.)


So my objection was essentially that your idea /cannot/ be "easily
translated" to C++, not by a traditional separate-compilation system.
You'll need a different programming model entirely.

If I understand what you mean then its only because the syntax you are using
to define the concept I am talking about? You are allowing for the
implementation of the function to be outside its declaration. Here I am not.

I was assuming 'foo' was a method of 'A'. If it's a global function,
your syntax is easy to implement, but also entirely redundant because
of the existing 'static' keyword.


Its very similar to classes but
with a different syntax. Its extending the idea of a function to allow
fields in it. (almost exactly like a class but a class is more general
purpose)

Well, you keep saying "almost exactly like a class" --- so why not
just use a class? In C++, you'd be describing "a class that implements
a public operator() method", also known (IIRC) as a "functor".
Real-life C++ code:

struct A;

struct FooFunction {
private:
A *my_a;
public:
int i;
void operator() (void);
FooFunction(A *a): i(0), my_a(a) {}
};

struct A {
const char *name;
FooFunction foo;
A(const char *n): name(n), foo(this) {}
};

void FooFunction::operator() (void)
{
printf("%s: %d\n", my_a->name, i);
++i;
}

int main()
{
A a("a");
A b("b");
a.foo();
a.foo();
b.foo();
b.foo();
printf("%d %d\n", a.foo.i, b.foo.i);
return 0;
}

This seems to do exactly what you're asking for, but in terms of
existing primitives, and in a way that doesn't break separate compilation.
(So I guess you could make a compiler that implemented all methods
as functors, and it would satisfy your need for convenient syntax
without breaking separate compilation, but at a terrible cost in
efficiency. I wouldn't recommend it.)

yes, this is basically what I'm talking about. But a here the functor should
be defined as a very special class... a class with only one method... since
its special we can reduce the overhead of defining it. I see no need to
define something like above when its very easy for the compiler to recognize
that the following is equivalent(except more convient).

void function A(const char *name)
{
public int i = 0;

printf("%s: %d\n", name, i);
++i;
}

Well, again, I was assuming you wanted 'foo' to be a method of 'A'.
If you want 'A' itself to be a functor, you can indeed cut out the
middleman:

struct FooFunction {
public:
int i;
FooFunction(): i(0) {}
void FooFunction::operator() (void) {
printf("%d\n", i);
++i;
}
};

int main()
{
FooFunction a, b;
a();
a();
b();
b();
printf("%d %d\n", a.i, b.i);
return 0;
}

(That's the same code from above, except I've moved the definition
of operator() up into the body of the class definition, to make it
more palatable to Java/C# junkies, and I've made 'main' define two
instances of the 'FooFunction' functor itself, instead of associating
them with instances of 'A'.)


Notice that you are using the struct A as a class while I'm using it as a
function. A function only has one "instantiation".

Not in your example, where you defined two instances of your 'A'
(my 'FooFunction'). I'm beginning to think you've never really
investigated how the compiler translates OO concepts into non-OO
code.

[...]
One could simply do the following for an equivalent code above:

void A(const char *name, int i = 0) {
printf("%s: %d\n", name, i);
++i;
}

int main()
{
A("a",0);
A("b",0);
A(?) = 1; // how to set state of i in A?

At this point in the program, there is no 'i'. 'i' is a parameter
to 'A', and only exists when 'A' is being executed. If you think 'i'
exists somewhere at this point, you are terribly confused.

printf("%d\n", A().i); // how to retrieve state of i in A?

There's no such 'i'.

return 0;
}

[...]
Anyways, I hope that clears up some things.

No, not really. I'm even more confused as to exactly what semantics
you're looking for. But I am starting to get a grasp on your level
of knowledge about C++/Java/C# OO concepts, which reassures me that
I may not be entirely at fault here. :)

Do you know C, or some other simple non-OO language? Could you
explain in terms of that language the behavior you want to get ---
where each piece of data is stored, how many pieces of data there
are, and so on? Then we could work up to an "OO" representation
(with plenty of convenient syntactic shortcuts) from there.

HTH,
-Arthur
.



Relevant Pages

  • Re: fields for methods?
    ... void A::foo{ ... but only by a compiler that is allowed to ... int static_instance i = 0; ... it totally breaks the idea of encapsulation, which is the reason a lot ...
    (comp.programming)
  • Re: Virtual Machine implementation problem, Please help me to spot the bug
    ... This is non-standard (Conceivably your compiler allows it ... tmp1 might not be correctly aligned for u32. ... void change_endian{ ... typedef unsigned int u32; ...
    (comp.lang.c)
  • Re: C Questions
    ... No prototype is given for this function, so the compiler cannot ... To prototype a function with no parameters, use void: ... %d takes an int argument, ...
    (comp.lang.c)
  • Re: The_Sage & void main()
    ... shall have a return type of type int but otherwise in all other respects ... > main may have the return type void then main may indeed have the ... If the compiler accepts void main, then you may use void main ... about whether void mainis conforming or not. ...
    (comp.lang.cpp)
  • Re: linking C++ functions in a C program
    ... contains one function named foo() which is compiled in C, ... Therefore, no matter how you classify bar(), this program ... void foo; ... guess the compiler can generate two references to foo, one adorned, ...
    (comp.lang.c)