Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #95500 > unrolled thread
| Started by | Andreas <nospam@invalid.invalid> |
|---|---|
| First post | 2016-11-01 13:15 +0100 |
| Last post | 2016-12-14 10:14 -0800 |
| Articles | 20 on this page of 60 — 16 participants |
Back to article view | Back to comp.lang.c
Aliasing and subtyping structs Andreas <nospam@invalid.invalid> - 2016-11-01 13:15 +0100
Re: Aliasing and subtyping structs Andreas <nospam@invalid.invalid> - 2016-11-01 13:34 +0100
Re: Aliasing and subtyping structs Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-11-01 15:27 +0000
Re: Aliasing and subtyping structs Andreas <nospam@invalid.invalid> - 2016-11-02 09:47 +0100
Re: Aliasing and subtyping structs Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-11-02 15:47 +0000
Re: Aliasing and subtyping structs Andreas <nospam@invalid.invalid> - 2016-11-08 00:24 +0100
Re: Aliasing and subtyping structs supercat@casperkitty.com - 2016-11-07 21:42 -0800
Re: Aliasing and subtyping structs <william@wilbur.25thandClement.com> - 2016-11-03 18:53 -0700
Re: Aliasing and subtyping structs supercat@casperkitty.com - 2016-11-04 09:56 -0700
Re: Aliasing and subtyping structs Andreas <nospam@invalid.invalid> - 2016-11-08 21:53 +0100
Re: Aliasing and subtyping structs James Kuyper <jameskuyper@verizon.net> - 2016-11-01 11:41 -0400
Re: Aliasing and subtyping structs Andreas <nospam@invalid.invalid> - 2016-11-02 09:55 +0100
"Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Anton Shepelev <anton.txt@g{oogle}mail.com> - 2016-11-21 16:59 +0300
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] supercat@casperkitty.com - 2016-11-21 07:32 -0800
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] "James R. Kuyper" <jameskuyper@verizon.net> - 2016-11-21 11:15 -0500
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] supercat@casperkitty.com - 2016-11-21 08:35 -0800
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Anton Shepelev <anton.txt@g{oogle}mail.com> - 2016-11-22 11:42 +0300
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] supercat@casperkitty.com - 2016-11-22 06:50 -0800
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-11-22 16:07 +0000
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] supercat@casperkitty.com - 2016-11-22 12:02 -0800
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-11-22 23:36 +0000
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] supercat@casperkitty.com - 2016-11-22 16:24 -0800
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Richard Damon <Richard@Damon-Family.org> - 2016-11-22 22:21 -0500
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] supercat@casperkitty.com - 2016-11-23 08:31 -0800
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] me <crisdunbar@gmail.com> - 2016-11-23 09:01 -0800
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] supercat@casperkitty.com - 2016-11-23 12:05 -0800
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Anton Shepelev <anton.txt@gmail.com> - 2016-11-22 23:23 +0300
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] "James R. Kuyper" <jameskuyper@verizon.net> - 2016-11-22 16:02 -0500
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] supercat@casperkitty.com - 2016-11-22 14:13 -0800
Re: container_of() macro Noob <root@127.0.0.1> - 2016-11-23 01:10 +0100
Re: container_of() macro <william@wilbur.25thandClement.com> - 2016-11-22 20:10 -0800
Re: container_of() macro "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-11-23 15:10 -0800
Re: container_of() macro David Brown <david.brown@hesbynett.no> - 2016-11-23 11:31 +0100
Re: container_of() macro Anton Shepelev <anton.txt@g{oogle}mail.com> - 2016-11-23 14:07 +0300
Re: container_of() macro supercat@casperkitty.com - 2016-11-23 08:41 -0800
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Anton Shepelev <anton.txt@gmail.com> - 2016-11-30 00:14 +0300
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] "James R. Kuyper" <jameskuyper@verizon.net> - 2016-11-29 17:23 -0500
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Anton Shepelev <anton.txt@gmail.com> - 2016-12-04 18:48 +0300
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] "James R. Kuyper" <jameskuyper@verizon.net> - 2016-12-04 12:17 -0500
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Anton Shepelev <anton.txt@gmail.com> - 2016-12-04 22:15 +0300
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] "James R. Kuyper" <jameskuyper@verizon.net> - 2016-12-04 15:06 -0500
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Anton Shepelev <anton.txt@gmail.com> - 2016-12-12 22:31 +0300
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-11-23 13:39 -0800
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] luser droog <luser.droog@gmail.com> - 2016-11-23 15:10 -0800
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-11-23 15:13 -0800
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] luser droog <luser.droog@gmail.com> - 2016-11-23 18:29 -0800
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Anton Shepelev <anton.txt@g{oogle}mail.com> - 2016-11-24 11:41 +0300
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Thiago Adams <thiago.adams@gmail.com> - 2016-11-24 03:29 -0800
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-11-24 17:37 -0800
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] supercat@casperkitty.com - 2016-11-25 09:55 -0800
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Thiago Adams <thiago.adams@gmail.com> - 2016-11-25 15:22 -0800
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-11-28 18:18 -0800
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Thiago Adams <thiago.adams@gmail.com> - 2016-11-29 04:48 -0800
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] supercat@casperkitty.com - 2016-11-29 07:28 -0800
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Thiago Adams <thiago.adams@gmail.com> - 2016-11-30 08:26 -0800
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] supercat@casperkitty.com - 2016-11-30 09:13 -0800
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-12-12 16:44 -0800
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Melzzzzz <mel@zzzzz.com> - 2016-12-13 02:18 +0100
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Thiago Adams <thiago.adams@gmail.com> - 2016-12-14 09:47 -0800
Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Thiago Adams <thiago.adams@gmail.com> - 2016-12-14 10:14 -0800
Page 3 of 3 — ← Prev page 1 2 [3]
| From | "James R. Kuyper" <jameskuyper@verizon.net> |
|---|---|
| Date | 2016-12-04 15:06 -0500 |
| Subject | Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] |
| Message-ID | <f99dce16-6d8d-df02-fcc4-e4a2f8c911ac@verizon.net> |
| In reply to | #97989 |
On 12/04/2016 02:15 PM, Anton Shepelev wrote:
> Given the code:
>
> struct a { int x; };
> struct c { struct a a; ... } c, * cp = & c;
> struct a * ap = & c.a;
>
> James R. Kuyper to Anton Shepelev:
>
>>> Would this:
>>>
>>> ap = (struct a *) cp; /* alias to cp */
>>> ap -> x
>>>
>>> be wrong?
>>
>> No, because the result of that conversion is a
>> pointer which is defined as pointing at cp.a.
>> That is an object with the declared type "struct
>> a", which is therefore also it's effective type.
>> Since the effective type of the object exactly
>> matches the type of the lvalue that is used to ac-
>> cess it, it is covered by the first item in 6.5p7:
>> "a type compatible with the effective type of the
>> object". "Two types have compatible type if their
>> types are the same." (6.2.7p1)
>
> Thanks. If the first field of a stucture has the
> same type as that of the pointer target then pointer
> conversion works. Will I violate aliasing if I re-
> place cp with &c, i.e.:
>
> cp = &c;
> ap = (struct a *)&c; /* alias to cp */
> ap -> x
Why are you worried about the possibility of getting a different answer
in this case? Since cp == &c, (struct a*)cp and (struct a*)&c have
precisely the same behavior, and in particular, precisely the same lack
of aliasing problems.
Unless I've missed some important point (which is not impossible - it's
happened before), it seems to me that you must be seriously
misunderstanding something, but your questions have not yet revealed to
me what that misunderstanding is. If you could explain, in detail, why
you thought there might be a problem, I might be able to identify what
it is that you're misunderstanding. Alternatively, that explanation
might help me identify the "important point" that I've been missing.
[toc] | [prev] | [next] | [standalone]
| From | Anton Shepelev <anton.txt@gmail.com> |
|---|---|
| Date | 2016-12-12 22:31 +0300 |
| Subject | Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] |
| Message-ID | <20161212223152.1b570d6da83626125db8ea80@gmail.com> |
| In reply to | #97995 |
James R. Kuyper to Anton Shepelev:
> > struct a { int x; };
> > struct c { struct a a; ... } c, * cp = & c;
> > struct a * ap = & c.a;
> >
> > Thanks. If the first field of a stucture has the
> > same type as that of the pointer target then pointer
> > conversion works. Will I violate aliasing if I re-
> > place cp with &c, i.e.:
> >
> > cp = &c;
> > ap = (struct a *)&c; /* alias to cp */
> > ap -> x
>
> Why are you worried about the possibility of get-
> ting a different answer in this case? Since cp ==
> &c, (struct a*)cp and (struct a*)&c have precisely
> the same behavior, and in particular, precisely
> the same lack of aliasing problems.
>
> Unless I've missed some important point (which is
> not impossible - it's happened before), it seems
> to me that you must be seriously misunderstanding
> something, but your questions have not yet re-
> vealed to me what that misunderstanding is. If you
> could explain, in detail, why you thought there
> might be a problem, I might be able to identify
> what it is that you're misunderstanding. Alterna-
> tively, that explanation might help me identify
> the "important point" that I've been missing.
No, no it is clearly I who lack understanding :-)
I am worried because C does not allow the use of two
pointers to the same location but with different
target types with the exceptions that are known as
the rules of strict aliasing. Why can cp and ap
alias in the example above? Is it because of the
following item in 6.5.7:
An object shall have its stored value accessed
only by an lvalue expression that has one of the
following types:
[...]
-- an aggregate or union type that includes one
of the aforementioned types among its mem-
bers (including, recursively, a member of a
subaggregate or contained union),
--
() ascii ribbon campaign - against html e-mail
/\ http://preview.tinyurl.com/qcy6mjc [archived]
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <invalid@invalid.invalid> |
|---|---|
| Date | 2016-11-23 13:39 -0800 |
| Subject | Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] |
| Message-ID | <o1528t$uaa$1@dont-email.me> |
| In reply to | #97197 |
On 11/21/2016 5:59 AM, Anton Shepelev wrote: > Andreas: > >> Hi all, [...] > Am I right in thinking that "Object-oriented pro- > gramming in C": > > http://www.cs.rit.edu/~ats/books/ooc.pdf > > is based entirely on the violation of strict alias- > ing? Well, I sort of like the following technique: http://pastebin.com/f52a443b1 Not even trying to make full OOP, but its fairly nice... ;^)
[toc] | [prev] | [next] | [standalone]
| From | luser droog <luser.droog@gmail.com> |
|---|---|
| Date | 2016-11-23 15:10 -0800 |
| Subject | Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] |
| Message-ID | <51b9526c-9a0f-4e1b-9b86-ef9eff06b558@googlegroups.com> |
| In reply to | #97361 |
On Wednesday, November 23, 2016 at 3:40:05 PM UTC-6, Chris M. Thomasson wrote: > On 11/21/2016 5:59 AM, Anton Shepelev wrote: > > Andreas: > > > >> Hi all, > [...] > > Am I right in thinking that "Object-oriented pro- > > gramming in C": > > > > http://www.cs.rit.edu/~ats/books/ooc.pdf > > > > is based entirely on the violation of strict alias- > > ing? > > Well, I sort of like the following technique: > > http://pastebin.com/f52a443b1 > > Not even trying to make full OOP, but its fairly nice... > > ;^) I tried looking at it, but I couldn't see the text under the failing-to-load Flash ads. Have you considered gist.github.com? I find it infinitely superior to pastebin.
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <invalid@invalid.invalid> |
|---|---|
| Date | 2016-11-23 15:13 -0800 |
| Subject | Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] |
| Message-ID | <o157om$k6u$2@dont-email.me> |
| In reply to | #97365 |
On 11/23/2016 3:10 PM, luser droog wrote:
> On Wednesday, November 23, 2016 at 3:40:05 PM UTC-6, Chris M. Thomasson wrote:
>> On 11/21/2016 5:59 AM, Anton Shepelev wrote:
>>> Andreas:
>>>
>>>> Hi all,
>> [...]
>>> Am I right in thinking that "Object-oriented pro-
>>> gramming in C":
>>>
>>> http://www.cs.rit.edu/~ats/books/ooc.pdf
>>>
>>> is based entirely on the violation of strict alias-
>>> ing?
>>
>> Well, I sort of like the following technique:
>>
>> http://pastebin.com/f52a443b1
>>
>> Not even trying to make full OOP, but its fairly nice...
>>
>> ;^)
>
> I tried looking at it, but I couldn't see the text under
> the failing-to-load Flash ads. Have you considered gist.github.com?
> I find it infinitely superior to pastebin.
Yikes! Okay, try this link:
http://pastebin.com/raw/f52a443b1
It should be raw text, also I will just post it here:
___________________________________________________
/* Interfaces
____________________________________________________________________*/
#include <stddef.h>
struct object_prv_vtable {
int (*fp_destroy) (void* const);
};
struct device_prv_vtable {
int (*fp_read) (void* const, void*, size_t);
int (*fp_write) (void* const, void const*, size_t);
};
struct device_vtable {
struct object_prv_vtable const object;
struct device_prv_vtable const device;
};
struct device {
struct device_vtable const* vtable;
};
#define object_destroy(mp_self) ( \
(mp_self)->vtable->object.fp_destroy((mp_self)) \
)
#define device_read(mp_self, mp_buf, mp_size) ( \
(mp_self)->vtable->device.fp_read((mp_self), (mp_buf), (mp_size)) \
)
#define device_write(mp_self, mp_buf, mp_size) ( \
(mp_self)->vtable->device.fp_write((mp_self), (mp_buf), (mp_size)) \
)
/* Sample Header (usb_drive.h)
____________________________________________________________________*/
#if ! defined(USB_HEADER_H)
#define USB_HEADER_H
extern int usb_drive_create(struct device** const);
#endif
/* Sample Impl (usb_drive.c)
____________________________________________________________________*/
/* #include "usb_drive.c" */
#include <stdio.h>
#include <stdlib.h>
struct usb_drive {
struct device device;
/* whatever */
};
static int usb_drive_object_destroy(void* const);
static int usb_drive_device_read(void* const, void*, size_t);
static int usb_drive_device_write(void* const, void const*, size_t);
static struct device_vtable const g_table = {
{ /* object */
usb_drive_object_destroy
},
{ /* device */
usb_drive_device_read,
usb_drive_device_write
}
};
int usb_drive_create(
struct device** const pself
) {
struct usb_drive* const self = malloc(sizeof(*self));
if (self) {
self->device.vtable = &g_table;
*pself = &self->device;
return 0;
}
return -1;
}
int usb_drive_object_destroy(
void* const self_
) {
struct usb_drive* const self = self_;
printf("usb_drive_object_destroy(%p)\n", (void*)self);
free(self_);
return 0;
}
int usb_drive_device_read(
void* const self_,
void* buf,
size_t size
) {
struct usb_drive* const self = self_;
printf("usb_drive_device_read(%p, %p, %lu)\n",
(void*)self, buf, (unsigned long)size);
return 0;
}
int usb_drive_device_write(
void* const self_,
void const* buf,
size_t size
) {
struct usb_drive* const self = self_;
printf("usb_drive_device_write(%p, %p, %lu)\n",
(void*)self, buf, (unsigned long)size);
return 0;
}
/* Sample Application
____________________________________________________________________*/
void read_write(
struct device* const self
) {
char buf[100];
device_read(self, buf, 50);
device_write(self, buf, 5);
}
int main(void) {
struct device* a_device;
if (! usb_drive_create(&a_device)) {
read_write(a_device);
object_destroy(a_device);
}
return 0;
}
___________________________________________________
[toc] | [prev] | [next] | [standalone]
| From | luser droog <luser.droog@gmail.com> |
|---|---|
| Date | 2016-11-23 18:29 -0800 |
| Subject | Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] |
| Message-ID | <402285ed-26bb-42df-80a0-80ac9161bacd@googlegroups.com> |
| In reply to | #97366 |
On Wednesday, November 23, 2016 at 5:13:45 PM UTC-6, Chris M. Thomasson wrote: > On 11/23/2016 3:10 PM, luser droog wrote: > > On Wednesday, November 23, 2016 at 3:40:05 PM UTC-6, Chris M. Thomasson wrote: > >> On 11/21/2016 5:59 AM, Anton Shepelev wrote: > >>> Andreas: > >>> > >>>> Hi all, > >> [...] > >>> Am I right in thinking that "Object-oriented pro- > >>> gramming in C": > >>> > >>> http://www.cs.rit.edu/~ats/books/ooc.pdf > >>> > >>> is based entirely on the violation of strict alias- > >>> ing? > >> > >> Well, I sort of like the following technique: > >> > >> http://pastebin.com/f52a443b1 > >> > >> Not even trying to make full OOP, but its fairly nice... > >> > >> ;^) > > > > I tried looking at it, but I couldn't see the text under > > the failing-to-load Flash ads. Have you considered gist.github.com? > > I find it infinitely superior to pastebin. > > Yikes! Okay, try this link: > > http://pastebin.com/raw/f52a443b1 > > It should be raw text, also I will just post it here: > ___________________________________________________ <snip> Excellent. Thanks for the help. I like it. Inheritance by composition is the current fav AFAIAA from OOP blogs. I wonder if some of the void* could be written as their actual types (or superclass type as appropriate) for more meaning to the reader, if not type-safety per se, ipso facto.
[toc] | [prev] | [next] | [standalone]
| From | Anton Shepelev <anton.txt@g{oogle}mail.com> |
|---|---|
| Date | 2016-11-24 11:41 +0300 |
| Subject | Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] |
| Message-ID | <20161124114112.a967cf16b075fe89a489e4a4@g{oogle}mail.com> |
| In reply to | #97366 |
Chris M. Thomasson qutoing
http://pastebin.com/raw/f52a443b1 :
>#include <stddef.h>
>
>
>struct object_prv_vtable {
> int (*fp_destroy) (void* const);
>};
>
>
>struct device_prv_vtable {
> int (*fp_read) (void* const, void*, size_t);
> int (*fp_write) (void* const, void const*, size_t);
>};
>
>
>struct device_vtable {
> struct object_prv_vtable const object;
> struct device_prv_vtable const device;
>};
>
>
>struct device {
> struct device_vtable const* vtable;
>};
>
>
>#define object_destroy(mp_self) ( \
> (mp_self)->vtable->object.fp_destroy((mp_self)) \
>)
>
>
>#define device_read(mp_self, mp_buf, mp_size) ( \
> (mp_self)->vtable->device.fp_read((mp_self), (mp_buf), (mp_size)) \
>)
>
>
>#define device_write(mp_self, mp_buf, mp_size) ( \
> (mp_self)->vtable->device.fp_write((mp_self), (mp_buf), (mp_size)) \
>)
What is the point of separating object- and device-
related functions -- having the same "object" inter-
face ( destroy() ) to different types of objects,
i.e. to objects with different sets of specific
functions?
--
() ascii ribbon campaign - against html e-mail
/\ http://preview.tinyurl.com/qcy6mjc [archived]
[toc] | [prev] | [next] | [standalone]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2016-11-24 03:29 -0800 |
| Subject | Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] |
| Message-ID | <4d9a9da5-e36e-4658-a5a2-c3bdbca7b123@googlegroups.com> |
| In reply to | #97366 |
On Wednesday, November 23, 2016 at 9:13:45 PM UTC-2, Chris M. Thomasson wrote: > On 11/23/2016 3:10 PM, luser droog wrote: > > On Wednesday, November 23, 2016 at 3:40:05 PM UTC-6, Chris M. Thomasson wrote: > >> On 11/21/2016 5:59 AM, Anton Shepelev wrote: > >>> Andreas: > >>> > >>>> Hi all, > >> [...] > >>> Am I right in thinking that "Object-oriented pro- > >>> gramming in C": > >>> > >>> http://www.cs.rit.edu/~ats/books/ooc.pdf > >>> > >>> is based entirely on the violation of strict alias- > >>> ing? > >> > >> Well, I sort of like the following technique: > >> > >> http://pastebin.com/f52a443b1 This is like the C++ implementation. I think this is the classic approach of java, C#, C++. The idea of "Interfaces". The problem with interfaces (virtual functions) is the coupling caused by the interfaces. You cannot solve problems independently from each other; instead, you have to deal with the best set of interfaces that fits the algorithms you have so far. When you need to add or remove algorithms then you have to refactoring your interfaces for the best set again, and doing this, sometimes, can break code that is already working. It is very easy to increase coupling with interfaces, and it's hard to keep the interface sets correct. When you do it, probably the interfaces are useful only in your specific project making your classes less reusable.
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <invalid@invalid.invalid> |
|---|---|
| Date | 2016-11-24 17:37 -0800 |
| Subject | Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] |
| Message-ID | <o184hq$oi9$1@dont-email.me> |
| In reply to | #97382 |
On 11/24/2016 3:29 AM, Thiago Adams wrote: > On Wednesday, November 23, 2016 at 9:13:45 PM UTC-2, Chris M. Thomasson wrote: >> On 11/23/2016 3:10 PM, luser droog wrote: >>> On Wednesday, November 23, 2016 at 3:40:05 PM UTC-6, Chris M. Thomasson wrote: >>>> On 11/21/2016 5:59 AM, Anton Shepelev wrote: >>>>> Andreas: >>>>> >>>>>> Hi all, >>>> [...] >>>>> Am I right in thinking that "Object-oriented pro- >>>>> gramming in C": >>>>> >>>>> http://www.cs.rit.edu/~ats/books/ooc.pdf >>>>> >>>>> is based entirely on the violation of strict alias- >>>>> ing? >>>> >>>> Well, I sort of like the following technique: >>>> >>>> http://pastebin.com/f52a443b1 > > This is like the C++ implementation. I think this is the classic approach of java, C#, C++. The idea of "Interfaces". > > The problem with interfaces (virtual functions) is the coupling caused by the interfaces. You cannot solve problems independently from each other; instead, you have to deal with the best set of interfaces that fits the algorithms you have so far. When you need to add or remove algorithms then you have to refactoring your interfaces for the best set again, and doing this, sometimes, can break code that is already working. It is very easy to increase coupling with interfaces, and it's hard to keep the interface sets correct. When you do it, probably the interfaces are useful only in your specific project making your classes less reusable. You are correct: There is a hard core binding with the interface API. How to make API flexible in this type of scheme? Well, it was never meant to be full OOP, so perhaps the inflexible can become flexible within the realm of certain narrow use cases? I did not want to add more forms of indirection... ;^o
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-11-25 09:55 -0800 |
| Subject | Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] |
| Message-ID | <4722afe4-e433-4784-bfa7-99e14b6376e7@googlegroups.com> |
| In reply to | #97442 |
On Thursday, November 24, 2016 at 7:37:18 PM UTC-6, Chris M. Thomasson wrote:
> You are correct: There is a hard core binding with the interface API.
> How to make API flexible in this type of scheme? Well, it was never
> meant to be full OOP, so perhaps the inflexible can become flexible
> within the realm of certain narrow use cases? I did not want to add more
> forms of indirection...
If a compiler treats pointers to any kind of struct as interchangeable for
purposes of aliasing, the Common Initial Sequence rule, or function-pointer
signature compatibility, that will allow things to be written very nicely:
struct baseThingFuncs {
void (*act1)(struct baseThing *it);
}
struct derived1Funcs {
void (*act1)(struct derived1 *it);
void (*act2)(struct derived1 *it);
}
struct baseThing { struct baseThingFuncs *f; int prop1, prop2; }
struct derived1 { struct derived1Funcs *f; int prop1, prop2, prop3; }
Code which has a pointer p of type struct baseThing* would be able to
invoke act1 upon it via p->f->act1(p), but if *p was a derived1, it
would be able to use all the members of derived1 or derived1Funcs without
needing a cast.
Nice and elegant, if one is willing to use the dialect of C associated with
the -fno-strict-aliasing flag.
[toc] | [prev] | [next] | [standalone]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2016-11-25 15:22 -0800 |
| Subject | Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] |
| Message-ID | <3d027f75-4a7c-4003-8801-b1e47594c583@googlegroups.com> |
| In reply to | #97442 |
On Thursday, November 24, 2016 at 11:37:18 PM UTC-2, Chris M. Thomasson wrote: > On 11/24/2016 3:29 AM, Thiago Adams wrote: > > On Wednesday, November 23, 2016 at 9:13:45 PM UTC-2, Chris M. Thomasson wrote: > >> On 11/23/2016 3:10 PM, luser droog wrote: > >>> On Wednesday, November 23, 2016 at 3:40:05 PM UTC-6, Chris M. Thomasson wrote: > >>>> On 11/21/2016 5:59 AM, Anton Shepelev wrote: > >>>>> Andreas: > >>>>> > >>>>>> Hi all, > >>>> [...] > >>>>> Am I right in thinking that "Object-oriented pro- > >>>>> gramming in C": > >>>>> > >>>>> http://www.cs.rit.edu/~ats/books/ooc.pdf > >>>>> > >>>>> is based entirely on the violation of strict alias- > >>>>> ing? > >>>> > >>>> Well, I sort of like the following technique: > >>>> > >>>> http://pastebin.com/f52a443b1 > > > > This is like the C++ implementation. I think this is the classic approach of java, C#, C++. The idea of "Interfaces". > > > > The problem with interfaces (virtual functions) is the coupling caused by the interfaces. You cannot solve problems independently from each other; instead, you have to deal with the best set of interfaces that fits the algorithms you have so far. When you need to add or remove algorithms then you have to refactoring your interfaces for the best set again, and doing this, sometimes, can break code that is already working. It is very easy to increase coupling with interfaces, and it's hard to keep the interface sets correct. When you do it, probably the interfaces are useful only in your specific project making your classes less reusable. > > You are correct: There is a hard core binding with the interface API. > How to make API flexible in this type of scheme? Well, it was never > meant to be full OOP, so perhaps the inflexible can become flexible > within the realm of certain narrow use cases? I did not want to add more > forms of indirection... > The problem of interfaces I mentioned is not a implementation problem, but a conceptual one. The "interface" approach is useful when you don't want to know the concrete type. For instance, you want to create an algorithm that works with no change with the code someone else will give to you and the only thing you know is that the code uses the same interface pointers. "plugin" I have a name for these polymorphism. I call it "open polymorphism" In case I know all the types I call "closed polymorphism" The closed polymorphism I implement using run-time selection using a number to identify the type. It is faster than vtable. The open polymorphism I use vtable-style. In C, because there is nothing ready to use, I have many other variations that are better in different cases like unions kind of "variant type"
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <invalid@invalid.invalid> |
|---|---|
| Date | 2016-11-28 18:18 -0800 |
| Subject | Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] |
| Message-ID | <o1ioeg$gp3$1@dont-email.me> |
| In reply to | #97488 |
On 11/25/2016 3:22 PM, Thiago Adams wrote: > On Thursday, November 24, 2016 at 11:37:18 PM UTC-2, Chris M. Thomasson wrote: >> On 11/24/2016 3:29 AM, Thiago Adams wrote: >>> On Wednesday, November 23, 2016 at 9:13:45 PM UTC-2, Chris M. Thomasson wrote: >>>> On 11/23/2016 3:10 PM, luser droog wrote: >>>>> On Wednesday, November 23, 2016 at 3:40:05 PM UTC-6, Chris M. Thomasson wrote: >>>>>> On 11/21/2016 5:59 AM, Anton Shepelev wrote: >>>>>>> Andreas: >>>>>>> >>>>>>>> Hi all, >>>>>> [...] >>>>>>> Am I right in thinking that "Object-oriented pro- >>>>>>> gramming in C": >>>>>>> >>>>>>> http://www.cs.rit.edu/~ats/books/ooc.pdf >>>>>>> >>>>>>> is based entirely on the violation of strict alias- >>>>>>> ing? >>>>>> >>>>>> Well, I sort of like the following technique: >>>>>> >>>>>> http://pastebin.com/f52a443b1 >>> >>> This is like the C++ implementation. I think this is the classic approach of java, C#, C++. The idea of "Interfaces". >>> >>> The problem with interfaces (virtual functions) is the coupling caused by the interfaces. You cannot solve problems independently from each other; instead, you have to deal with the best set of interfaces that fits the algorithms you have so far. When you need to add or remove algorithms then you have to refactoring your interfaces for the best set again, and doing this, sometimes, can break code that is already working. It is very easy to increase coupling with interfaces, and it's hard to keep the interface sets correct. When you do it, probably the interfaces are useful only in your specific project making your classes less reusable. >> >> You are correct: There is a hard core binding with the interface API. >> How to make API flexible in this type of scheme? Well, it was never >> meant to be full OOP, so perhaps the inflexible can become flexible >> within the realm of certain narrow use cases? I did not want to add more >> forms of indirection... >> > The problem of interfaces I mentioned is not a implementation problem, but a conceptual one. > > The "interface" approach is useful when you don't want to know the concrete type. For instance, you want to create an algorithm that works with no change with the code someone else will give to you and the only thing you know is that the code uses the same interface pointers. "plugin" > > I have a name for these polymorphism. > I call it "open polymorphism" > > In case I know all the types I call "closed polymorphism" > > The closed polymorphism I implement using run-time selection using a number to identify the type. It is faster than vtable. How are you doing this selection/dispatch? > > The open polymorphism I use vtable-style. > > In C, because there is nothing ready to use, I have many other variations that are better in different cases like unions kind of "variant type" Reminds me of the XEvent union in X11.
[toc] | [prev] | [next] | [standalone]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2016-11-29 04:48 -0800 |
| Subject | Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] |
| Message-ID | <a644cb1a-04d9-4028-b413-be7458f91f84@googlegroups.com> |
| In reply to | #97704 |
On Tuesday, November 29, 2016 at 12:18:12 AM UTC-2, Chris M. Thomasson wrote:
> On 11/25/2016 3:22 PM, Thiago Adams wrote:
> > On Thursday, November 24, 2016 at 11:37:18 PM UTC-2, Chris M. Thomasson wrote:
> >> On 11/24/2016 3:29 AM, Thiago Adams wrote:
> >>> On Wednesday, November 23, 2016 at 9:13:45 PM UTC-2, Chris M. Thomasson wrote:
> >>>> On 11/23/2016 3:10 PM, luser droog wrote:
> >>>>> On Wednesday, November 23, 2016 at 3:40:05 PM UTC-6, Chris M. Thomasson wrote:
> >>>>>> On 11/21/2016 5:59 AM, Anton Shepelev wrote:
> >>>>>>> Andreas:
> >>>>>>>
> >>>>>>>> Hi all,
> >>>>>> [...]
> >>>>>>> Am I right in thinking that "Object-oriented pro-
> >>>>>>> gramming in C":
> >>>>>>>
> >>>>>>> http://www.cs.rit.edu/~ats/books/ooc.pdf
> >>>>>>>
> >>>>>>> is based entirely on the violation of strict alias-
> >>>>>>> ing?
> >>>>>>
> >>>>>> Well, I sort of like the following technique:
> >>>>>>
> >>>>>> http://pastebin.com/f52a443b1
> >>>
> >>> This is like the C++ implementation. I think this is the classic approach of java, C#, C++. The idea of "Interfaces".
> >>>
> >>> The problem with interfaces (virtual functions) is the coupling caused by the interfaces. You cannot solve problems independently from each other; instead, you have to deal with the best set of interfaces that fits the algorithms you have so far. When you need to add or remove algorithms then you have to refactoring your interfaces for the best set again, and doing this, sometimes, can break code that is already working. It is very easy to increase coupling with interfaces, and it's hard to keep the interface sets correct. When you do it, probably the interfaces are useful only in your specific project making your classes less reusable.
> >>
> >> You are correct: There is a hard core binding with the interface API.
> >> How to make API flexible in this type of scheme? Well, it was never
> >> meant to be full OOP, so perhaps the inflexible can become flexible
> >> within the realm of certain narrow use cases? I did not want to add more
> >> forms of indirection...
> >>
> > The problem of interfaces I mentioned is not a implementation problem, but a conceptual one.
> >
> > The "interface" approach is useful when you don't want to know the concrete type. For instance, you want to create an algorithm that works with no change with the code someone else will give to you and the only thing you know is that the code uses the same interface pointers. "plugin"
> >
> > I have a name for these polymorphism.
> > I call it "open polymorphism"
> >
> > In case I know all the types I call "closed polymorphism"
> >
> > The closed polymorphism I implement using run-time selection using a number to identify the type. It is faster than vtable.
>
> How are you doing this selection/dispatch?
like this:
typedef enum { Type1_ID, Type2_ID.. } Types;
typedef struct { Types Type; } TypePtr;
struct { TypePtr Type; ... } Type1;
#define TYPE1_INIT { {Type1_ID}, ... }
struct { TypePtr Type; ... } Type2;
#define TYPE2_INIT { {Type2_ID}, ... }
typedef TypePtr Shape;
CAST(Shape, Type1);
CAST(Shape, Type2);
#define Case(T) case T_##ID:
void Shape_Print(Shape* p)
{
switch (p->Type)
{
Case(Type1):
Type1_Print((Type1*)p);
break;
Case(Type2):
Type2_Print((Type2*)p);
break;
default:
assert(false);
break;
}
}
//I guess here is the controversial point of this topic
//(this works for me)
#define CAST(T1, T2) \
inline T2* T1_##As##_T2(T1* p) { \
return (p->Type == T2_##ID) ? (T2*)p : 0;\
}\
inline T1* T2_##As##_T1(T2* p) { return (T1*)p; }
----
How it differs from vtable-style?
Let's say I have Circle and Cat objects.
The initial design was IObject, IAnimal, IShape.
Now I have to add a new algorithm Print.
It was not at the initial design. Where do I add it now?
Do I put inside the IObject interface or I create a new Interface IPrintable?
The puzzle of interface definition begins and it's not a localized/independent problem.
To add a Print into the IObject interface I have to see if it makes sense for all objects derived from IObject.
Lets see other case. I have IControl that is a interface for widgets.
Initially I put the method "Draw" at this interface because all of my objects derived from IControl had to be drawn.
At some point, I have to add a new object similar of IControl but that doesn't need to be draw.
Then I have to create a new interface called IDraw and move Draw from IControl to IDraw.
When a new algorithm needs to be added I may have to reorganize the Interfaces and the types.
The types are now depending on many interfaces adjusted for the needs of that program globally adjusted.
With this type-selection approach you can solve the problem locally at the collection point. (you can think in small parts)
For instance, for the IControl "Draw" problem I can adjust my for-each-draw to just ignore the new type that doesn't need to be draw.
The new type, or the old ones don't need any changes.
You can create a new specialized algorithm as well without to worry about the interface relationship.
You can have many types of Print algorithms applied differently for different types without to worry it that type is for all types or not.
And you can reuse a type. If you don't need polymorphism just remove 1 line from the begging of you struct and you are done.
But with this approach you cannot add a new type without to change the algorithm. Or a new unknown type in some collection. "plugins"
--
What a language could do is to create the type selection for us.
Imagine a new language:
typedef (Box | Circle) Shape;
void Func(Shape* p)
{
//we known that shape can be only Box or Circle
// "closed polymorphism"
//please language make this dispatch for me
Shape_Draw(p);
}
void Box_Draw(Box* p) {...}
void Circle_Draw(Circle* p) {...}
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-11-29 07:28 -0800 |
| Subject | Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] |
| Message-ID | <453f371f-5ce3-4848-abd0-e2cf0341d23f@googlegroups.com> |
| In reply to | #97727 |
On Tuesday, November 29, 2016 at 6:48:48 AM UTC-6, Thiago Adams wrote: > Now I have to add a new algorithm Print. > It was not at the initial design. Where do I add it now? If things are added in a well-defined sequence, such that there will be an entity that knows all the functions, then it will be possible to have code which was compiled earlier pass its function and its size to the all-knowing entity, and ask it to allocate and return a pointer to a table which includes all functions the entity knows about. If the all-knowing entity knows of a print function, but it's given a table which doesn't include it, it could fill in the "print" slot with either a stub that returns an error, or with a function that uses some supported method of rendering to generate an image of the object and then uses its own logic to print that.
[toc] | [prev] | [next] | [standalone]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2016-11-30 08:26 -0800 |
| Subject | Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] |
| Message-ID | <2924507a-f8c4-447c-bd1d-c15fb1ac1e46@googlegroups.com> |
| In reply to | #97734 |
On Tuesday, November 29, 2016 at 1:28:39 PM UTC-2, supe...@casperkitty.com wrote: > On Tuesday, November 29, 2016 at 6:48:48 AM UTC-6, Thiago Adams wrote: > > Now I have to add a new algorithm Print. > > It was not at the initial design. Where do I add it now? > > If things are added in a well-defined sequence, such that there will be an > entity that knows all the functions, then it will be possible to have code > which was compiled earlier pass its function and its size to the all-knowing > entity, and ask it to allocate and return a pointer to a table which includes > all functions the entity knows about. If the all-knowing entity knows of a > print function, but it's given a table which doesn't include it, it could > fill in the "print" slot with either a stub that returns an error, or with a > function that uses some supported method of rendering to generate an image > of the object and then uses its own logic to print that. Do you mean runtime-vtable-build?
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-11-30 09:13 -0800 |
| Subject | Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] |
| Message-ID | <60ba08e0-2bb8-447b-90bf-bee69f17e9a7@googlegroups.com> |
| In reply to | #97780 |
On Wednesday, November 30, 2016 at 10:26:29 AM UTC-6, Thiago Adams wrote: > On Tuesday, November 29, 2016 at 1:28:39 PM UTC-2, supercat wrote: > > If things are added in a well-defined sequence, such that there will be an > > entity that knows all the functions, then it will be possible to have code > > which was compiled earlier pass its function and its size to the all-knowing > > entity, and ask it to allocate and return a pointer to a table which includes > > all functions the entity knows about. If the all-knowing entity knows of a > > print function, but it's given a table which doesn't include it, it could > > fill in the "print" slot with either a stub that returns an error, or with a > > function that uses some supported method of rendering to generate an image > > of the object and then uses its own logic to print that. > > Do you mean runtime-vtable-build? In a sense, but many such systems also require runtime computation of offsets. If functions are added to the library in a fixed universally- agreed-upon sequence, such that given any two versions of the vtable, one will be a subset of the other, all offsets will be known at compile time. Consequently, there would be a one-time cost at system startup but all code which used the vtables would run at full-speed [unlike some dynamic-vtable-generation approaches where every function call would require an extra variable fetch]. Actually, on many systems it would be possible to have a build step between the compiler and linker which could look for symbols with certain magic names and perform all the necessary adjustments at link time. For example, if every "class" declared a const vtable whose name followed a certain convention and an extern vtable whose name was related to the first, a tool could search all object files for definitions of the first form and define suitably-expanded vtables of the second form. The exact means by which the utility would identify the contents of all the appropriate tables would depend upon the system's object file format, of course.
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <invalid@invalid.invalid> |
|---|---|
| Date | 2016-12-12 16:44 -0800 |
| Subject | Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] |
| Message-ID | <o2ng71$rgt$1@dont-email.me> |
| In reply to | #97727 |
On 11/29/2016 4:48 AM, Thiago Adams wrote:
> On Tuesday, November 29, 2016 at 12:18:12 AM UTC-2, Chris M. Thomasson wrote:
>> On 11/25/2016 3:22 PM, Thiago Adams wrote:
>>> On Thursday, November 24, 2016 at 11:37:18 PM UTC-2, Chris M. Thomasson wrote:
>>>> On 11/24/2016 3:29 AM, Thiago Adams wrote:
>>>>> On Wednesday, November 23, 2016 at 9:13:45 PM UTC-2, Chris M. Thomasson wrote:
>>>>>> On 11/23/2016 3:10 PM, luser droog wrote:
>>>>>>> On Wednesday, November 23, 2016 at 3:40:05 PM UTC-6, Chris M. Thomasson wrote:
>>>>>>>> On 11/21/2016 5:59 AM, Anton Shepelev wrote:
>>>>>>>>> Andreas:
>>>>>>>>>
>>>>>>>>>> Hi all,
>>>>>>>> [...]
>>>>>>>>> Am I right in thinking that "Object-oriented pro-
>>>>>>>>> gramming in C":
>>>>>>>>>
>>>>>>>>> http://www.cs.rit.edu/~ats/books/ooc.pdf
>>>>>>>>>
>>>>>>>>> is based entirely on the violation of strict alias-
>>>>>>>>> ing?
>>>>>>>>
>>>>>>>> Well, I sort of like the following technique:
>>>>>>>>
>>>>>>>> http://pastebin.com/f52a443b1
>>>>>
>>>>> This is like the C++ implementation. I think this is the classic approach of java, C#, C++. The idea of "Interfaces".
>>>>>
>>>>> The problem with interfaces (virtual functions) is the coupling caused by the interfaces. You cannot solve problems independently from each other; instead, you have to deal with the best set of interfaces that fits the algorithms you have so far. When you need to add or remove algorithms then you have to refactoring your interfaces for the best set again, and doing this, sometimes, can break code that is already working. It is very easy to increase coupling with interfaces, and it's hard to keep the interface sets correct. When you do it, probably the interfaces are useful only in your specific project making your classes less reusable.
>>>>
>>>> You are correct: There is a hard core binding with the interface API.
>>>> How to make API flexible in this type of scheme? Well, it was never
>>>> meant to be full OOP, so perhaps the inflexible can become flexible
>>>> within the realm of certain narrow use cases? I did not want to add more
>>>> forms of indirection...
>>>>
>>> The problem of interfaces I mentioned is not a implementation problem, but a conceptual one.
>>>
>>> The "interface" approach is useful when you don't want to know the concrete type. For instance, you want to create an algorithm that works with no change with the code someone else will give to you and the only thing you know is that the code uses the same interface pointers. "plugin"
>>>
>>> I have a name for these polymorphism.
>>> I call it "open polymorphism"
>>>
>>> In case I know all the types I call "closed polymorphism"
>>>
>>> The closed polymorphism I implement using run-time selection using a number to identify the type. It is faster than vtable.
>>
>> How are you doing this selection/dispatch?
>
> like this:
>
> typedef enum { Type1_ID, Type2_ID.. } Types;
> typedef struct { Types Type; } TypePtr;
> struct { TypePtr Type; ... } Type1;
> #define TYPE1_INIT { {Type1_ID}, ... }
> struct { TypePtr Type; ... } Type2;
> #define TYPE2_INIT { {Type2_ID}, ... }
>
>
> typedef TypePtr Shape;
> CAST(Shape, Type1);
> CAST(Shape, Type2);
>
> #define Case(T) case T_##ID:
>
> void Shape_Print(Shape* p)
> {
> switch (p->Type)
> {
> Case(Type1):
> Type1_Print((Type1*)p);
> break;
>
> Case(Type2):
> Type2_Print((Type2*)p);
> break;
>
> default:
> assert(false);
> break;
> }
> }
I see. So, if we add a new Shape TypeN, we have to add a new entry here
in Shape_Print and add a new entry wrt the CAST macro, right?. That's fine.
>
> //I guess here is the controversial point of this topic
> //(this works for me)
>
> #define CAST(T1, T2) \
> inline T2* T1_##As##_T2(T1* p) { \
> return (p->Type == T2_##ID) ? (T2*)p : 0;\
> }\
> inline T1* T2_##As##_T1(T2* p) { return (T1*)p; }
Concat in pre-processor is fine.
>
>
> ----
>
> How it differs from vtable-style?
>
> Let's say I have Circle and Cat objects.
> The initial design was IObject, IAnimal, IShape.
> Now I have to add a new algorithm Print.
> It was not at the initial design. Where do I add it now?
> Do I put inside the IObject interface or I create a new Interface IPrintable?
> The puzzle of interface definition begins and it's not a localized/independent problem.
> To add a Print into the IObject interface I have to see if it makes sense for all objects derived from IObject.
> Lets see other case. I have IControl that is a interface for widgets.
> Initially I put the method "Draw" at this interface because all of my objects derived from IControl had to be drawn.
> At some point, I have to add a new object similar of IControl but that doesn't need to be draw.
> Then I have to create a new interface called IDraw and move Draw from IControl to IDraw.
> When a new algorithm needs to be added I may have to reorganize the Interfaces and the types.
> The types are now depending on many interfaces adjusted for the needs of that program globally adjusted.
>
>
> With this type-selection approach you can solve the problem locally at the collection point. (you can think in small parts)
I agree with you. Keep in mind that my little interface code worked
great wrt my problem set. Think of testing a dozen mutex impls using a
common interface for a "mutex".
>
> For instance, for the IControl "Draw" problem I can adjust my for-each-draw to just ignore the new type that doesn't need to be draw.
> The new type, or the old ones don't need any changes.
>
>
> You can create a new specialized algorithm as well without to worry about the interface relationship.
> You can have many types of Print algorithms applied differently for different types without to worry it that type is for all types or not.
> And you can reuse a type. If you don't need polymorphism just remove 1 line from the begging of you struct and you are done.
>
> But with this approach you cannot add a new type without to change the algorithm. Or a new unknown type in some collection. "plugins"
Yup. I have used the crude minimalist interface code for plugins. It
works well, and keeps a standard interface for said plugins.
>
> --
> What a language could do is to create the type selection for us.
>
> Imagine a new language:
>
> typedef (Box | Circle) Shape;
>
> void Func(Shape* p)
> {
> //we known that shape can be only Box or Circle
> // "closed polymorphism"
>
> //please language make this dispatch for me
> Shape_Draw(p);
> }
>
> void Box_Draw(Box* p) {...}
> void Circle_Draw(Circle* p) {...}
Interesting.
:^)
[toc] | [prev] | [next] | [standalone]
| From | Melzzzzz <mel@zzzzz.com> |
|---|---|
| Date | 2016-12-13 02:18 +0100 |
| Subject | Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] |
| Message-ID | <20161213021845.1779de2d@maxa-pc> |
| In reply to | #99161 |
On Mon, 12 Dec 2016 16:44:37 -0800
"Chris M. Thomasson" <invalid@invalid.invalid> wrote:
> On 11/29/2016 4:48 AM, Thiago Adams wrote:
> >
> > --
> > What a language could do is to create the type selection for us.
> >
> > Imagine a new language:
> >
> > typedef (Box | Circle) Shape;
> >
> > void Func(Shape* p)
> > {
> > //we known that shape can be only Box or Circle
> > // "closed polymorphism"
> >
> > //please language make this dispatch for me
> > Shape_Draw(p);
> > }
> >
> > void Box_Draw(Box* p) {...}
> > void Circle_Draw(Circle* p) {...}
>
> Interesting.
>
> :^)
Haskell:
data Shape = Circle Double | Rectangle Double Double | Square Double
deriving (Show,Read)
perimeter (Circle r) = 2*r*pi
perimeter (Rectangle x y) = 2*(x+y)
perimeter (Square x) = 4*x
shapes = [Circle 2.4, Rectangle 3.1 4.4, Square 2.1]
main = do
putStrLn $ show $ map perimeter shapes
putStrLn $ show shapes
--
press any key to continue or any other to quit...
[toc] | [prev] | [next] | [standalone]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2016-12-14 09:47 -0800 |
| Subject | Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] |
| Message-ID | <55a27566-b4e8-4b5f-bc41-3df3e8c7df9d@googlegroups.com> |
| In reply to | #99161 |
On Monday, December 12, 2016 at 10:44:42 PM UTC-2, Chris M. Thomasson wrote:
> On 11/29/2016 4:48 AM, Thiago Adams wrote:
> > On Tuesday, November 29, 2016 at 12:18:12 AM UTC-2, Chris M. Thomasson wrote:
> >> On 11/25/2016 3:22 PM, Thiago Adams wrote:
> >>> On Thursday, November 24, 2016 at 11:37:18 PM UTC-2, Chris M. Thomasson wrote:
> >>>> On 11/24/2016 3:29 AM, Thiago Adams wrote:
> >>>>> On Wednesday, November 23, 2016 at 9:13:45 PM UTC-2, Chris M. Thomasson wrote:
> >>>>>> On 11/23/2016 3:10 PM, luser droog wrote:
> >>>>>>> On Wednesday, November 23, 2016 at 3:40:05 PM UTC-6, Chris M. Thomasson wrote:
> >>>>>>>> On 11/21/2016 5:59 AM, Anton Shepelev wrote:
> >>>>>>>>> Andreas:
> >>>>>>>>>
> >>>>>>>>>> Hi all,
> >>>>>>>> [...]
> >>>>>>>>> Am I right in thinking that "Object-oriented pro-
> >>>>>>>>> gramming in C":
> >>>>>>>>>
> >>>>>>>>> http://www.cs.rit.edu/~ats/books/ooc.pdf
> >>>>>>>>>
> >>>>>>>>> is based entirely on the violation of strict alias-
> >>>>>>>>> ing?
> >>>>>>>>
> >>>>>>>> Well, I sort of like the following technique:
> >>>>>>>>
> >>>>>>>> http://pastebin.com/f52a443b1
> >>>>>
> >>>>> This is like the C++ implementation. I think this is the classic approach of java, C#, C++. The idea of "Interfaces".
> >>>>>
> >>>>> The problem with interfaces (virtual functions) is the coupling caused by the interfaces. You cannot solve problems independently from each other; instead, you have to deal with the best set of interfaces that fits the algorithms you have so far. When you need to add or remove algorithms then you have to refactoring your interfaces for the best set again, and doing this, sometimes, can break code that is already working. It is very easy to increase coupling with interfaces, and it's hard to keep the interface sets correct. When you do it, probably the interfaces are useful only in your specific project making your classes less reusable.
> >>>>
> >>>> You are correct: There is a hard core binding with the interface API.
> >>>> How to make API flexible in this type of scheme? Well, it was never
> >>>> meant to be full OOP, so perhaps the inflexible can become flexible
> >>>> within the realm of certain narrow use cases? I did not want to add more
> >>>> forms of indirection...
> >>>>
> >>> The problem of interfaces I mentioned is not a implementation problem, but a conceptual one.
> >>>
> >>> The "interface" approach is useful when you don't want to know the concrete type. For instance, you want to create an algorithm that works with no change with the code someone else will give to you and the only thing you know is that the code uses the same interface pointers. "plugin"
> >>>
> >>> I have a name for these polymorphism.
> >>> I call it "open polymorphism"
> >>>
> >>> In case I know all the types I call "closed polymorphism"
> >>>
> >>> The closed polymorphism I implement using run-time selection using a number to identify the type. It is faster than vtable.
> >>
> >> How are you doing this selection/dispatch?
> >
> > like this:
> >
> > typedef enum { Type1_ID, Type2_ID.. } Types;
> > typedef struct { Types Type; } TypePtr;
> > struct { TypePtr Type; ... } Type1;
> > #define TYPE1_INIT { {Type1_ID}, ... }
> > struct { TypePtr Type; ... } Type2;
> > #define TYPE2_INIT { {Type2_ID}, ... }
> >
> >
> > typedef TypePtr Shape;
> > CAST(Shape, Type1);
> > CAST(Shape, Type2);
> >
> > #define Case(T) case T_##ID:
> >
> > void Shape_Print(Shape* p)
> > {
> > switch (p->Type)
> > {
> > Case(Type1):
> > Type1_Print((Type1*)p);
> > break;
> >
> > Case(Type2):
> > Type2_Print((Type2*)p);
> > break;
> >
> > default:
> > assert(false);
> > break;
> > }
> > }
>
> I see. So, if we add a new Shape TypeN, we have to add a new entry here
> in Shape_Print and add a new entry wrt the CAST macro, right?. That's fine.
The cast macro, creates the cast functions. Because the language would not check any of the casts these functions have a very important role. If the function exists then the cast is valid.
The auto complete from IDEs also shows what are the valid casts when I type Shape_As_... I receive the options.
[toc] | [prev] | [next] | [standalone]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2016-12-14 10:14 -0800 |
| Subject | Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] |
| Message-ID | <19bc0471-3f9b-43d2-b170-572dfab0077e@googlegroups.com> |
| In reply to | #99361 |
On Wednesday, December 14, 2016 at 3:47:45 PM UTC-2, Thiago Adams wrote:
> On Monday, December 12, 2016 at 10:44:42 PM UTC-2, Chris M. Thomasson wrote:
> > On 11/29/2016 4:48 AM, Thiago Adams wrote:
> > > On Tuesday, November 29, 2016 at 12:18:12 AM UTC-2, Chris M. Thomasson wrote:
> > >> On 11/25/2016 3:22 PM, Thiago Adams wrote:
> > >>> On Thursday, November 24, 2016 at 11:37:18 PM UTC-2, Chris M. Thomasson wrote:
> > >>>> On 11/24/2016 3:29 AM, Thiago Adams wrote:
> > >>>>> On Wednesday, November 23, 2016 at 9:13:45 PM UTC-2, Chris M. Thomasson wrote:
> > >>>>>> On 11/23/2016 3:10 PM, luser droog wrote:
> > >>>>>>> On Wednesday, November 23, 2016 at 3:40:05 PM UTC-6, Chris M. Thomasson wrote:
> > >>>>>>>> On 11/21/2016 5:59 AM, Anton Shepelev wrote:
> > >>>>>>>>> Andreas:
> > >>>>>>>>>
> > >>>>>>>>>> Hi all,
> > >>>>>>>> [...]
> > >>>>>>>>> Am I right in thinking that "Object-oriented pro-
> > >>>>>>>>> gramming in C":
> > >>>>>>>>>
> > >>>>>>>>> http://www.cs.rit.edu/~ats/books/ooc.pdf
> > >>>>>>>>>
> > >>>>>>>>> is based entirely on the violation of strict alias-
> > >>>>>>>>> ing?
> > >>>>>>>>
> > >>>>>>>> Well, I sort of like the following technique:
> > >>>>>>>>
> > >>>>>>>> http://pastebin.com/f52a443b1
> > >>>>>
> > >>>>> This is like the C++ implementation. I think this is the classic approach of java, C#, C++. The idea of "Interfaces".
> > >>>>>
> > >>>>> The problem with interfaces (virtual functions) is the coupling caused by the interfaces. You cannot solve problems independently from each other; instead, you have to deal with the best set of interfaces that fits the algorithms you have so far. When you need to add or remove algorithms then you have to refactoring your interfaces for the best set again, and doing this, sometimes, can break code that is already working. It is very easy to increase coupling with interfaces, and it's hard to keep the interface sets correct. When you do it, probably the interfaces are useful only in your specific project making your classes less reusable.
> > >>>>
> > >>>> You are correct: There is a hard core binding with the interface API.
> > >>>> How to make API flexible in this type of scheme? Well, it was never
> > >>>> meant to be full OOP, so perhaps the inflexible can become flexible
> > >>>> within the realm of certain narrow use cases? I did not want to add more
> > >>>> forms of indirection...
> > >>>>
> > >>> The problem of interfaces I mentioned is not a implementation problem, but a conceptual one.
> > >>>
> > >>> The "interface" approach is useful when you don't want to know the concrete type. For instance, you want to create an algorithm that works with no change with the code someone else will give to you and the only thing you know is that the code uses the same interface pointers. "plugin"
> > >>>
> > >>> I have a name for these polymorphism.
> > >>> I call it "open polymorphism"
> > >>>
> > >>> In case I know all the types I call "closed polymorphism"
> > >>>
> > >>> The closed polymorphism I implement using run-time selection using a number to identify the type. It is faster than vtable.
> > >>
> > >> How are you doing this selection/dispatch?
> > >
> > > like this:
> > >
> > > typedef enum { Type1_ID, Type2_ID.. } Types;
> > > typedef struct { Types Type; } TypePtr;
> > > struct { TypePtr Type; ... } Type1;
> > > #define TYPE1_INIT { {Type1_ID}, ... }
> > > struct { TypePtr Type; ... } Type2;
> > > #define TYPE2_INIT { {Type2_ID}, ... }
> > >
> > >
> > > typedef TypePtr Shape;
> > > CAST(Shape, Type1);
> > > CAST(Shape, Type2);
> > >
> > > #define Case(T) case T_##ID:
> > >
> > > void Shape_Print(Shape* p)
> > > {
> > > switch (p->Type)
> > > {
> > > Case(Type1):
> > > Type1_Print((Type1*)p);
> > > break;
> > >
> > > Case(Type2):
> > > Type2_Print((Type2*)p);
> > > break;
> > >
> > > default:
> > > assert(false);
> > > break;
> > > }
> > > }
> >
> > I see. So, if we add a new Shape TypeN, we have to add a new entry here
> > in Shape_Print and add a new entry wrt the CAST macro, right?. That's fine.
>
>
> The cast macro, creates the cast functions. Because the language would not check any of the casts these functions have a very important role. If the function exists then the cast is valid.
> The auto complete from IDEs also shows what are the valid casts when I type Shape_As_... I receive the options.
Something interesting is that at some level I have to iterate myself on types to see what are the possible casts.
Some of the casts just logical renaming.
For instance:
Shape = Circle | Box;
Animal = Cat | Dog;
Anything = Shape | Animal;
The implementation of Anything, Shape and Animal are the same thing (TypePtr).
But I can cast Anything_As_Shape.
I also can cast Anything to Box, because Anything can be Shape that can be Box.
I am considering to create some DSL to create these casts for me.
[toc] | [prev] | [standalone]
Page 3 of 3 — ← Prev page 1 2 [3]
Back to top | Article view | comp.lang.c
csiph-web