473,406 Members | 2,273 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,406 software developers and data experts.

Cyclic dependency in throw declaration

Hi,

I am unable to get the following to compile
Expand|Select|Wrap|Line Numbers
  1. struct m
  2. {
  3.         void n ( ) throw ( m ) ;
  4. } ;
  5.  
  6. int main ( )
  7. {
  8. }
I am using g++ ( GNU version of c++ compiler ) to compile. It throws the following error:
Expand|Select|Wrap|Line Numbers
  1. m.cpp:3: error: invalid use of incomplete type 'struct m'
  2. m.cpp:2: error: forward declaration of 'struct m'
  3.  
Apr 15 '09 #1
12 2894
weaknessforcats
9,208 Expert Mod 8TB
You cannot throw an m object from inside the struct m declaration. At this point the compiler does not know what an m object is exactly. Like, is there a default constructor, or maybe more data members, etc..

As a result it doesn't know what code to generate. That is, not until it reaches the end of the struct declaration.

You will need to throw an m*.

Since the compiler has seen "struct m", that is enough information to allow an m*.
Apr 19 '09 #2
Hi weaknessforcats,

Thanks for your kind reply. I knew that there should be a simple workaround for this design problem. The solution that you suggested is very simple, I just throw a pointer to the struct instead of the actual object.

Warm Regards,
Gaura
Apr 19 '09 #3
Hi,

Sorry folks. I hadn't actually tried compiling the above code with the change included. The change that we thought would work was: throwing a pointer to 'struct m' rather than throwing an instance of 'struct m' itself. To be more clear what I am trying to say is that the code below
Expand|Select|Wrap|Line Numbers
  1. struct m
  2. {
  3.     void n ( ) throw ( m * ) ;
  4.     int val ;
  5. } ;
  6.  
  7. int main ( )
  8. {
  9. return 0 ;
  10. }
  11.  
should compile when using g++. BUT it doesn't! Surprising! Trying to compile the code above gives the same compilation errors that I quoted earlier in this thread. Desperate to make the above piece of code compile, I modified the 3rd line to
Expand|Select|Wrap|Line Numbers
  1. void n ( ) throw ( m * * )
and miraculously it compiled! What could be the reason that g++ doesn't allow throwing a pointer to 'struct m' but allows a pointer to a pointer to 'struct m' ? Could any one enlighten me ?

Warm Regards,
Gaura
May 4 '09 #4
weaknessforcats
9,208 Expert Mod 8TB
I have no idea why g++ is doing this. m** or m* is still just a pointer.

I use Visual Studio.NET but this tool does not yet support exception specifications so I can't compile your code exactly. VS currently just ignores the exception specification.
May 4 '09 #5
RRick
463 Expert 256MB
Well, you learn something every day. It looks like a class can not throw itself from a member function. g++ keeps complaining about a using an incomplete class in the throw declaration.

Why this is so is beyond me. If you are really interested in an answer I would go to the source and talk to the C++ news group (comp.lang.c++). They have been my source for weird questions like this. If you do find out what is going on, be sure to let us know.


WARNING WILL ROBINSON: A word of caution is needed here. An exception is a resource and in C++ that means you have to deal with it. If you throw a pointer to something, that means you have new/malloc the object before you throw it and also clean it up sometime later.

The best way to deal with exceptions is to let the C++ compiler deal automatically with the resources itself. This means you throw a real object and catch references to that object. That way you can inspect and re-throw an exception any number of times.
May 5 '09 #6
Hi,

Well, the reason I am trying to solve this weird problem is because of the following design that I want to implement.

I have an 'exception' class that no other function must be able to throw except a select group of functions. I want the compiler to prohibit people who use my code the capability of throwing instances of my exception class. However they will still be able catch objects of the exception class. Why do I want to do this ? This brings clarity to the working of the code - the source of all instances of my exception class is only one - my code. I could have easily acheived this in Java by making the constructor of my exception class package-private ( which I acheive by not specifying any access modifier for the constructor ) . I would then put the exception class inside the package where my code will be making new instances of the exception class. But C++ lacks this kind of access modifier. Now how should I design my exception class to achieve this in C++ ?

I resorted to making the constructor of my exception class as private and making all the functions of my code which will be allowed to throw instances of this exception class, as 'friend's of the class. A representative piece of code of this design is given here:
Expand|Select|Wrap|Line Numbers
  1. struct m
  2. {
  3.         private:
  4.                 m ( )
  5.                 { }
  6.  
  7.         friend void myFunc ( ) throw ( m ) ;
  8. } ;
  9.  
  10. int main ( )
  11. {
  12.         return 0 ;
  13. }
But unfortunately as I narrate at the beginning of this thread, the g++ compiler doesn't allow me to do this. Does anyone have a better idea of going about implementing the design that I have just talked about.

Warm Regards,
Gaura
May 5 '09 #7
Did you try exporting your function outside the class body?

Expand|Select|Wrap|Line Numbers
  1. class myException // you should really ": public std::exception" all custom exceptions
  2. {
  3. private:
  4.      myException MakeObj();
  5.  
  6.      friend classA;
  7.      friend classB;
  8.      etc.....
  9. }
  10.  
  11. // This in a separate compile module (e.g. another cpp file).
  12. // If you do this in the header, including it twice will cause linker errors.
  13. myException myException::MakeObj()
  14. {
  15.      return myException();
  16. }
This method allows you to specify which classes can instance the exception.

Now this code has a lot of overhead, but I expect your compiler would be reasonable enough not to instance the same object, copy it, and then destroy the first instance after optimization.
May 5 '09 #8
RRick
463 Expert 256MB
The above posting is one solution, but has the problem of modifying the exception class for every new accessing object.

You can minimize those additions by making an application base class a friend of the exception, but now you have to hide the application base class from the users and only the methods in the application base class would be able to throw the exceptions.


The most useful exception class structure I have found, is creating an application exception base class. All of the application's exceptions are derived from that base class. To catch any application exception you just catch the base class.

To limit access for this system the application object's would have to be friends to both the base and derived exception classes. Ugh.


I have found that when you can try to program around a language's limitation, the solution is not usually optimal or maintainable or very pretty. In this case, why is the limiting the creation of the exception so important?

I have found that most applications use their own exceptions. The general rule is that you use yours and I use mine and everyone is happy.
May 5 '09 #9
Hi RRick,

You got to the root of my problem. I am being too obsessive about not allowing others to create instances of my exception class. It's not going to hurt anyone, if they do. However on the positive side my quest did spark off an instructive discussion at the comp.lang.c++ group. click here to see.
This thread does answer the questions raised here. Rick, I have got a few more things to say about handling exceptions in C++ in my next post. ( Lot of work pressure at office ! )

Warm Regards,
Gaura
May 7 '09 #10
weaknessforcats
9,208 Expert Mod 8TB
You might read this: http://bytes.com/topic/c/insights/65...erns-singleton
May 7 '09 #11
Hi,

The singleton design pattern was an interesting article on controlling the number of instances that a user of the class can create.

The warning that RRick gave near the beginning of the thread about throwing exception as pointer to an object is something that we need to heed. It's better to drop the idea of throwing pointer to objects, otherwise it would lead to increased complexity in maintaining the code.

Warm Regards,
Gaura
May 8 '09 #12
RRick
463 Expert 256MB
You're getting the right idea about exceptions; there are good and bad ways to deal with them. These issues can be as bad as crash and burn (i.e. throwing an exception within a destructor) or as pernicious and difficult to find as a memory leak.

FYI: The following link has some of the caveats for exception creation and handling. http://www.parashift.com/c++-faq-lit....html#faq-17.3

Cheers.
May 9 '09 #13

Sign in to post your reply or Sign up for a free account.

Similar topics

7
by: Brian Sabolik | last post by:
I'm not sure if I've broken any Object Oriented rules or not, but ... I have projects in 2 different solutions that need to use each other's methods. Therefore I may have an "update" method in...
3
by: Dennis Lerche | last post by:
Hi I have a problem regarding cyclic dependency, yeahh I know bad design. But right at this moment I can't see how it should be redesigned to avoid this. The problem is that I just can't get it...
4
by: Alex Sedow | last post by:
For example, System.dll contains assembly reference to System.XML.dll, System.XML.dll refers to System.dll. Some another open projects contain cyclic assembly dependencies too. How C# compiler...
3
by: fc2004 | last post by:
Hi, Is there any tools that could report where cyclic header dependency happens? this would be useful when working with a large project where tens or hundreds of headers files may form complex...
4
by: sakis.panou | last post by:
Hi all, Can anyone explain to me why the copy constructor of the COuterClass is getting called for this one? Let me start by saying I reckon this is seriously bad way of implementing anything of...
10
by: toton | last post by:
Hi I have a class called Session, which stores a vector of Page, like vector<PageAlso each Page need's to know the Session to which it is attached. Thus I have, (the classes has many other...
1
by: pallav | last post by:
I have two header files, circuit.h and latch.h that reference each other and are causing a cyclic dependency. latch.h file #include "circuit.h" typedef boost::shared_ptr<struct LatchLatchPtr;...
3
by: soup007 | last post by:
Hi, I am having some difficulties with cyclic dependency between two classes. Situation is something like following - ///A.h #include "B.h" class A { { int X; public:
11
by: sgurukrupagmailcom | last post by:
Hi, When searching for a solution to my problem I stumbled upon 'Curiously Recurring Template Pattern' see link. This is how the pattern looks: template < typename T > struct y { } ;
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
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...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
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...

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.