473,732 Members | 2,214 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Semi-circular definitions (plus circular references)

Is there an elegant way to deal with semi-circular definitions?

Semi-circular definition:
A { B };
B { *A };
Circular reference:
A { *B };
B { *A };

The problems arise when there are more semi-circular definitions and
circular references.

Consider the following sample code:

--- inc1.h ---
#ifndef INC1_INCLUDE
#define INC1_INCLUDE

typedef struct _struc2
{
struct _struc1 *s1;
} struc2;
typedef struct _struc3
{
struct _struc1 *s1;
} struc3;

typedef struct _struc1
{
struct _struc2 s2;
struct _struc3 s3;
} struc1;

typedef struct _struc4
{
struct _struc1 s1;
} struc4;

#endif

--- test.cpp ---

#include "inc1.h"

int main()
{
struc1 s1;
s1.s2;

return 1;
}

------

The previous code is obviously correct.
Now I want to split the include file in two separated files.
The original include file contains 4 definitions:
A
B
C
D
The problem arises when the splitting is such that the original include
file cannot be obtained by reattaching the 2 include files.
For Example, inc1.h could contain A and D, and inc2.h B and C.

--- inc1.h ---
#ifndef INC1_INCLUDE
#define INC1_INCLUDE

#include "inc2.h"

typedef struct _struc2
{
struct _struc1 *s1;
} struc2;

typedef struct _struc4
{
struct _struc1 s1;
} struc4;

#endif

--- inc2.h ---
#ifndef INC2_INCLUDE
#define INC2_INCLUDE

#include "inc1.h"

typedef struct _struc3
{
struct _struc1 *s1;
} struc3;

typedef struct _struc1
{
struct _struc2 s2;
struct _struc3 s3;
} struc1;

#endif

-------

Someone affirms that this situation is index of bad organization, but I
disagree, then I do not seek an obvious workaround, but a solution to
the *original* problem.
Yes, I could use a pointer instead of the struct itself, but I do not
want to use an unneeded indirection.
I could even use a dummy structure but that solution is very inelegant.

Is there a particular directive which instructs the compiler to analyze
the entire file before giving up?

Is there a better solution than using a bunch of #if..[...]..#endif? :)

Thanks, Kiuhnm
Jul 22 '05 #1
16 2834
Kiuhnm wrote:
Is there an elegant way to deal with semi-circular definitions?


You just need to restructure it a bit. Here's my solution which seems
to work:

inc1.h:
---------

#ifndef INC1_INCLUDE
#define INC1_INCLUDE


typedef struct _struc2
{
struct _struc1 *s1;
} struc2;
#include "inc2.h"
typedef struct _struc4
{
struct _struc1 s1;
} struc4;
#endif

----------------
inc2.h:
----------------#include "inc1.h"
#ifndef INC2_INCLUDE
#define INC2_INCLUDE


typedef struct _struc3
{
struct _struc1 *s1;
} struc3;


typedef struct _struc1
{
struct _struc2 s2;
struct _struc3 s3;
} struc1;


#endif
--------

Compiles cleanly for me.

Jon
----
Learn to program using Linux assembly language
http://www.cafeshops.com/bartlettpublish.8640017
Jul 22 '05 #2
Jonathan Bartlett wrote:
Kiuhnm wrote:
Is there an elegant way to deal with semi-circular definitions?


You just need to restructure it a bit. Here's my solution which seems
to work:

[cut]

You recomposed the original file!
Is it always possible?
No, unfortunately.

--- inc1.h ---
s1 {s3}
s2 {s4}
--- inc2.h ---
s3 {s2}
s4 {}
--------------

Let "a < b" mean "a must appear before b".

s3 < s1,
s4 < s2
s2 < s3

=>

s4 < s2 < s3 < s1

then that's the only correct arrangement.

By partially reordering the structures in each include file, we obtain:
--- inc1.h ---
s2 {s4}
s1 {s3}
--- inc2.h ---
s4 {}
s3 {s2}
--------------

s2 s1
s4 s3

How can we obtain that arrangement without splitting any file?
Why are the compilers so stupid?
The compiler could simply perform a first pass and compile a table of
the sizes of all the structures and then use that table in the
successive passes.

Perhaps the documentation of the preprocessor could help...

Thank you anyway!

Kiuhnm
Jul 22 '05 #3
Kiuhnm wrote:
You recomposed the original file!
Is it always possible?
No, unfortunately.


Yes, it is *always* possible to rearrange the way data structures are
declared so that entities are declared before they are needed. It may
entail declaring each data structure in its own header file, but it is
always possible.

Consider what happens when a truly circular dependency is declared:

struct A { B b };
struct B ( A a };

This implies that B includes a copy of A, which includes a copy of B,
which includes a copy of A, ad infinitum. This struct has infinite size
and is not possible to instantiate.

In other words, in order for a data structure to have finite size, its
composition graph must have no loops. Thus, all finite data structures
can be described by a sequence of declarations with no "forward dependency".

Sometimes it is not possible to properly declare data structures if
multiple data structures are declared within one or more header files.
Your problem in this case in not with the language definition or the
compiler, but with the way that your modules are organized.

-dr
Jul 22 '05 #4
Dave Rahardja wrote:
Kiuhnm wrote:
You recomposed the original file!
Is it always possible?
No, unfortunately.

Yes, it is *always* possible to rearrange the way data structures are
declared so that entities are declared before they are needed. It may
entail declaring each data structure in its own header file, but it is
always possible.


I've just *proved* that (with the restrictions I imposed) it is impossible.
Sometimes it is not possible to properly declare data structures if
multiple data structures are declared within one or more header files.
Your problem in this case in not with the language definition or the
compiler, but with the way that your modules are organized.


No, the problem resides in the c/c++ compilers/language.
If something could have been done better, then it should have been done
better.
A smart compiler would scan the entire preprocessed file and build a
graph with the dependencies in order to quickly determine the structure
sizes.
I can understand that you consider the compiler something untouchable,
but, IMHO, a compiler is a tool, not a religion.

Do you know C#? In this language, the forward definitions are handled
seamlessly.
I think I'll pass to C#... or maybe I could write a little preprocessor
for the C++ compiler (portability is not an issue to me).

Kiuhnm
Jul 22 '05 #5
Kiuhnm wrote:
Dave Rahardja wrote:
Kiuhnm wrote:

You recomposed the original file!
Is it always possible?
No, unfortunately.
Yes, it is *always* possible to rearrange the way data structures are
declared so that entities are declared before they are needed. It may
entail declaring each data structure in its own header file, but it is
always possible.


I've just *proved* that (with the restrictions I imposed) it is impossible.


If you cannot change the headers, C++ cannot do
anything for you.
Sometimes it is not possible to properly declare data structures if
multiple data structures are declared within one or more header files.
Your problem in this case in not with the language definition or the
compiler, but with the way that your modules are organized.


No, the problem resides in the c/c++ compilers/language.


It is because of the language, but it is not a
problem, it is called "type checking". To use a
name, you need to declare it and to instanciate a
class, you need its definition.
If something could have been done better, then it should have been done
better.
A smart compiler would scan the entire preprocessed file and build a
graph with the dependencies in order to quickly determine the structure
sizes.
If you think compilers are dumb, write one.
I can understand that you consider the compiler something untouchable,
but, IMHO, a compiler is a tool, not a religion.
Do you know C#?
No one is forcing you to use C++. If a language
cannot do what you want, change it! Languages are
tools, not religions.
In this language, the forward definitions are handled seamlessly.


If I recall correctly, C# only deals with
references, not with stack-based objects. You
never need the size of the classes in this case.
It's like replacing automatic objects with
pointers in your example, which solves your
problem. Before falling in love with this, read
about the problems (and advantages) associated
with this behavior.
Jonathan
Jul 22 '05 #6
Jonathan Mcdougall wrote:
If you cannot change the headers, C++ cannot do anything for you.
The headers are thematically divided, then I don't want to move a
definition from a file to another.
It is because of the language, but it is not a problem, it is called
"type checking". To use a name, you need to declare it and to
instanciate a class, you need its definition.
I know, but you omitted a detail: C++ uses a "chronologi cal type
checking". The mathematical language is ABSOLUTELY UNAMBIGUOUS and
doesn't have such a limitation.
Besides, why should the programmer tolerate such a restriction when a
simple algorithm could completely resolve the problem?
If you think compilers are dumb, write one.
Very humorous, but I prefer to write a preprocessor.
If I recall correctly, C# only deals with references, not with
stack-based objects. You never need the size of the classes in this
case. It's like replacing automatic objects with pointers in your
example, which solves your problem. Before falling in love with this,
read about the problems (and advantages) associated with this behavior.


Then C# is not a language for me (I'm developing a real-time OS).

Kiuhnm
Jul 22 '05 #7

"Kiuhnm" <ki******@yahoo .it.invalid> a écrit dans le message de news:
qN************* *********@news3 .tin.it...
Jonathan Mcdougall wrote:
If you cannot change the headers, C++ cannot do anything for you.
The headers are thematically divided, then I don't want to move a
definition from a file to another.


There are situations where you must sacrifice a bit of design in order to
make the program work. It seems to be your case, but you only can tell.
It is because of the language, but it is not a problem, it is called
"type checking". To use a name, you need to declare it and to
instanciate a class, you need its definition.


I know, but you omitted a detail: C++ uses a "chronologi cal type
checking". The mathematical language is ABSOLUTELY UNAMBIGUOUS and doesn't
have such a limitation.


I don't understand that.
Besides, why should the programmer tolerate such a restriction when a
simple algorithm could completely resolve the problem?


Because that's how the language works.

A a;

class A
{
};

does not work, not because the compiler cannot make it work (postponing the
checking of names until the translation unit is completly processed would be
a solution to this example but has many drawbacks for others, more
complicated constructs), but because the language mandates it.
Jonathan
Jul 22 '05 #8
Jonathan Mcdougall wrote:
There are situations where you must sacrifice a bit of design in order to
make the program work. It seems to be your case, but you only can tell.
I moved the most referenced structure to a separated file.
I know, but you omitted a detail: C++ uses a "chronologi cal type
checking". The mathematical language is ABSOLUTELY UNAMBIGUOUS and doesn't
have such a limitation.


I don't understand that.


|u+v| <= |u|+|v| for each u,v in C(T, R).

u and v are used before the definition.

Another example:
for each x > 0, there exists K in N : d(u_k,u_h) < eps, for each k,h in
N, h,k > K.
A a;

class A
{
};

does not work, not because the compiler cannot make it work (postponing the
checking of names until the translation unit is completly processed would be
a solution to this example but has many drawbacks for others, more
complicated constructs), but because the language mandates it.


The languages C and C++ are a bit incoherent: it is possible to define a
pointer to an undefined object, because you will need the object
definition only when you will use the pointer, but it is impossible to
define an object which contains an undefined object, even if the object
definition will not be used before the first instantiation.
You call that a feature? IMHO, that is a flaw.

Kiuhnm
Jul 22 '05 #9
"Kiuhnm" <ki******@yahoo .it.invalid> a écrit dans le message de news:
Vl************* *********@news3 .tin.it...
Jonathan Mcdougall wrote:
A a;

class A
{
};

does not work, not because the compiler cannot make it work (postponing
the checking of names until the translation unit is completly processed
would be a solution to this example but has many drawbacks for others,
more complicated constructs), but because the language mandates it.
The languages C and C++ are a bit incoherent: it is possible to define a
pointer to an undefined object,


Undefined, but declared.
because you will need the object definition only when you will use the
pointer,
Not when you use it, only when you need the definition of the class.

class A;

void f(A *a);

int main()
{
A *a=0;
f(a);
}

This example does not need the definition of A, only its declaration.
but it is impossible to define an object which contains an undefined
object,
Of course, because its size is needed. If you have a pointer or reference,
you don't need the class' definition to define one.
You call that a feature? IMHO, that is a flaw.


Requiring the class's definition for everything would not only be
unnecessary but also a pain. It is the base for a common technique of
reducing compilation dependencies.

I wouldn't say C++ does a good job at separating modules, but I think the
language *is* consistent. When the compiler does not need the class's
definition to operate, you don't have to specify it.
Jonathan
Jul 22 '05 #10

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

Similar topics

2
3779
by: Dennis M. Marks | last post by:
I am never sure of when a semi-colon is required in javascript. Is there a definite rule? -- Dennis M. Marks -----= Posted via Newsfeeds.Com, Uncensored Usenet News =----- http://www.newsfeeds.com - The #1 Newsgroup Service in the World! -----== Over 100,000 Newsgroups - 19 Different Servers! =-----
7
20950
by: jhomp ssens | last post by:
I would like to create a pulldown menu which is semi-transparent....that is, you can see the text and graphics behind it when it is pulled down. The effect I'm looking for can be seen at http://www.countrywide.com. Are there any good tutorials which can show me how to do this with CSS?
2
3698
by: David Scemama | last post by:
Hi, I'm looking for a way to display semi graphic characters in a multi line text control or in a rich text control. I've tried with all the characters of the extended ASCII table (code page 437), they appear correctly except the semi graphic ones. Please help ... Thanks a lot
27
3176
by: StevePBurgess | last post by:
With a string of authors such as: Carson, David, Milne, Rebecca, Pakes, Francis J., Shalev, Karen, Shawyer, Andrea I would like to write a function to change every other comma into a semi colon (thereby defining where one name ends and the next begins). I could do it by writing a complex (and slow) procedure - but is there a quick way of doing it using regular expressions, for example?
2
2718
by: Trond Michelsen | last post by:
Hi. I have a transparent PNG-image that I would like to display on top of the rest of the web page. I've already got this part working. But, I'd like the background (as in "the part of the image that is transparent"), to be semi transparent instead. So, I've wrapped the image in a div-tag with the style "opacity: .70" instead. This gives me pretty much the semi transparency that I'm looking for, except that this makes the entire image...
2
2317
by: James Stroud | last post by:
Hello All, I am trying to create a semi-standalone with the vendor python on OS X 10.4 (python 2.3.5). I tried to include some packages with both --packages from the command and the 'packages' option in setup.py. While the packages were nicely included in the application bundle in both cases (at Contents/Resources/lib/python2.3/), they were not found by python when the program was launched, giving the error: "ImportError: No module...
0
1922
by: James Arnold | last post by:
I am trying to use a semi transparent PNG as the form background, allowing you to see through certain parts. The intention is similar to a skinnable form like launchy, with semi-transparent pixels (not just .MakeTransparent or Form.Opacity). Also similar to the Adobe splash screens which the feather and drop shadow. By overriding the OnPaint method and manually drawing a PNG onto the form background I can achieve this effect, but it does...
9
4115
by: JamesF1982 | last post by:
Hey everyone, My question is related to HTML, Javascript, CSS and ASP.NET but i think it belongs here! Upon an event i am trying to add a semi-transparent colour across the page so the background is obscurred but i also set a div with a known ID to exist above this. My current method has been to on the fly create a div which gets the screen height/width with javascript and then sets the image. However, my div is created but does not...
3
29772
by: nigel | last post by:
Hi, I'm using VBA to export data from a table direct to a CSV file DoCmd.TransferText acExportDelim, , "ExportTable", filePath this produced a file with COMMA separated values, until...my computer got fried and the repair shop re-installed Windows XP in French (I
26
3043
by: machineghost | last post by:
First off, let me just say that as someone with no DBA training whatsoever, any help I can get with this issue will be very, very much appreciated. My company recently migrated our database from DB2 v7 to DB2 v9. We hired a consultant to help us, and things went pretty smoothly ... up until a few weeks after, when a co-worker tried to insert JavaScript in to our database. That's when we learned that v9, unlike v7, has a problem with...
0
8946
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9447
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9307
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
6735
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6031
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4550
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
3261
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2721
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2180
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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

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