Thread: "error: incomplete type is not allowed"

  1. #1
    King of the Internet Fahrenheit's Avatar
    Join Date
    Oct 2001
    Posts
    128

    "error: incomplete type is not allowed"

    I've been coding for a long time, and never have I faced this error message before. I am writing a compiler for a language that dynamically compiles itself on other platforms.. while the specifications for that are not the problem, it's an odd problem I got when I tried "modularizing" my applications with C++ and classes.


    Code:
    struct Type ;
      struct Class ;
      struct Function ;
      struct Variable ;
      struct Definition ;
      
      typedef std::deque<std::string> StringList ;
      typedef StringList::iterator RegisteredString;
    
      typedef std::deque<Type> TypeList ;
      typedef TypeList::iterator RegisteredType;
    
      typedef std::deque<Class> ClassList ;
      typedef ClassList::iterator RegisteredClass;
    
      typedef std::deque<Variable> VariableList ;
      typedef VariableList::iterator RegisteredVariable ;
    
      typedef std::deque<Function> FunctionList ;
      typedef FunctionList::iterator RegisteredFunction ;
    
      enum Level {
    	Private, Public, Protected
      } ;
    
    #include <Type.hpp> // requires class
    #include <Variable.hpp> // requires type
    #include <Function.hpp> // requires type / variable
    #include <Class.hpp> // requires variable / function
    #include <Definition.hpp> // requires everything
    Type.hpp

    Code:
    struct TETRA Type 
    {
      RegisteredClass rc ;
      dword array_depth ;
      dword flags ;
    
      operator == (const Type & t) ;
      operator != (const Type & t) ;
    } ;
    Variable.hpp

    Code:
    struct TETRA Variable 
    {
      RegisteredString name ;
      RegisteredType type ;
    
      Level level ;
    
      operator== (const Variable & v) ;
      operator!= (const Variable & v) ;
    
      operator== (const Function & f) ;
      operator!= (const Function & f) ;
    
      operator== (const Class & c) ;
      operator!= (const Class & c) ; 
    
      operator std::string () ;
    } ;
    Function.hpp

    Code:
    struct TETRA Function 
    {
      RegisteredString name ;
      RegisteredType type ;
      Level level ;
    
      VariableList arguments ;
      VariableList variables ;
    
      RegisteredVariable AddVariable (const Variable & v) ;
      RegisteredVariable AddArgument (const Variable & v) ;
    
      operator== (const Variable & v) ;
      operator!= (const Variable & v) ;
    
      operator== (const Function & f) ;
      operator!= (const Function & f) ;
    
      operator== (const Class & c) ;
      operator!= (const Class & c) ;
    
      operator std::string () ;
    } ;
    Class.hpp
    Code:
    struct TETRA Class 
    {
      RegisteredString name ;
    
      VariableList members ;
      FunctionList functions ;
    
      operator== (const Variable & v) ;
      operator!= (const Variable & v) ;
    
      operator== (const Function & f) ;
      operator!= (const Function & f) ;
    
      operator== (const Class & c) ;
      operator!= (const Class & c) ;
    
      operator std::string() ;
    
      RegisteredVariable AddMember (const Variable & v) ;
      RegisteredFunction AddFunction (const Function & f) ;
    }
    ;
    Definition.hpp ( I don't think it matters, but whatever. )

    Code:
    struct TETRA Definition
    {
      StringList strings ;
      TypeList types ;
      ClassList classes ;
    
      Definition () ;
    
      RegisteredType AddType (const Type & t) ;
    
      inline idx GetTypeIndex (const RegisteredType rt) {
    	return (idx) (rt - types.begin()) ;
      }
      
      void ReadTypes (std::istream & is, dword count) ;
      void WriteTypes (std::ostream & os) ;
    
      RegisteredString AddString (const std::string & s) ;
      
      inline idx GetStringIndex (const RegisteredString rs) {
    	return (idx) ( rs - strings.begin () ) ;
      }
    
      void WriteStrings (std::ostream & os) ;
      void ReadStrings (std::istream & is, dword count) ;
    
      RegisteredClass AddClass (const Class & c) ;
    
      RegisteredClass FindClass (const std::string & s) ;
      RegisteredClass FindClass (const RegisteredString s) ;
    
      void Read (std::istream & is, dword flags) ;
      void Write (std::ostream & os, dword flags) ;
    
      ~Definition () ;
    } ;
    I get about ~60 error messages from the headers, usually something like

    Compiling with Intel C++ 8.0
    String.cpp
    c:\Program Files\Microsoft Visual Studio .NET\Vc7/include/deque(59): error: incomplete type is not allowed
    _DEQUESIZ = sizeof (_Ty) <= 1 ? 16
    ^
    detected during instantiation of class "std::deque<_Ty, _Ax> [with _Ty=Tetra::Type, _Ax=std::allocator<Tetra::Type>]" at line 49 of "D:\tetra\runtime\Tetra.hpp"

    I can paste them all if necessary, I don't want the flood this topic however. Any help is appreciated, and if you have questions about what I am doing in the code just ask. My forte is C and lowish level stuff, I'm really just now starting to dabble in STL and C++.

    Thanks in advance.
    Last edited by w00tsoft; 05-08-2005 at 08:32 PM.

  2. #2
    Registered User
    Join Date
    Aug 2003
    Posts
    470
    The problem is that std::deque<C>::deque probably requires the definition of C to be present. For instance, it might have code such as C* c = new C[45]. The compiler cannot allocate memory without knowing the size of C. And without knowing the full type of C, the compiler doesn't know what fields C has.

  3. #3
    King of the Internet Fahrenheit's Avatar
    Join Date
    Oct 2001
    Posts
    128
    Everytime i've encountered something with circular references before, forward declarations have fixed it. Why not in this example?

  4. #4
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    Everytime i've encountered something with circular references before, forward declarations have fixed it. Why not in this example?
    Try this:
    Code:
    class Car;
    class Apple;
    
    class Apple
    {
    	Car aCar;
    };
    
    class Car
    {
    	Apple anApple;
    };
    
    int main()
    {
    	
    	
    
    	return 0;
    }

  5. #5
    King of the Internet Fahrenheit's Avatar
    Join Date
    Oct 2001
    Posts
    128
    I don't see where i'm doing that... I assume it's in some STL container that I don't understand.

  6. #6
    Toaster Zach L.'s Avatar
    Join Date
    Aug 2001
    Posts
    2,686
    First file... all the typedefs... then the #includes with the definitions.
    The word rap as it applies to music is the result of a peculiar phonological rule which has stripped the word of its initial voiceless velar stop.

  7. #7
    King of the Internet Fahrenheit's Avatar
    Join Date
    Oct 2001
    Posts
    128
    It's obviously not the typedefs, since what I was doing there is legal. I wrote a small workaround with the typedefs still in front and it worked. I suppose it must be an oddity in Microsoft's implementation of the STL.

    Code:
    struct Type ;
      struct Class ;
      struct Function ;
      struct Variable ;
      struct Definition ;
    
      template<class T> struct Registered { 
    	T * data ; 
    	idx index ; 
    
    	Registered () { 	}
    
    	Registered (const Registered<T> & r)
    	{
    	  data = r.data ;
    	  index = r.index ;
    	}
    
    	Registered(T & d, idx i) {
    	  data = &d ;
    	  index = i ;
    	}
    
    	operator= (const Registered<T> & r) 
    	{
    	  data = r.data ;
    	  index = r.index;
    	}
    
    	T & operator* () const { return *data ; }
      } ; 
      
      typedef std::deque<std::string> StringList ;
      
      typedef StringList::const_iterator StringIter ;
      typedef Registered<std::string> RegisteredString;
    
      typedef std::deque<Type> TypeList ;
      typedef Registered<Type> RegisteredType;
    
      typedef std::deque<Class> ClassList ;
      typedef Registered<Class> RegisteredClass;
    
      typedef std::deque<Variable> VariableList ;
    
      typedef Registered<Variable> RegisteredVariable ;
    
      typedef std::deque<Function> FunctionList ;
      typedef Registered<Function> RegisteredFunction ;

  8. #8
    Registered User
    Join Date
    Aug 2003
    Posts
    470
    Everytime i've encountered something with circular references before, forward declarations have fixed it. Why not in this example?
    The preprocessor expands #include "type.hpp" inplace in the file. The definition of Type uses a RegisteredClass. RegisteredClass is a type alias for typedef ClassList::iterator. ClassList is a type alias for std::deque<Class>. Class hasn't been defined before in your source. So, std::deque gets an incomplete type for one of it's template parameters and likely uses this incomplete type.

  9. #9
    King of the Internet Fahrenheit's Avatar
    Join Date
    Oct 2001
    Posts
    128
    well since I fixed my problem and it works now i'll stop replying after this post, but forward declarations let you do that ;/ it's defined later in the source so it isn't "incomplete"

  10. #10
    Registered User
    Join Date
    Aug 2003
    Posts
    470
    well since I fixed my problem and it works now i'll stop replying after this post, but forward declarations let you do that ;/ it's defined later in the source so it isn't "incomplete"
    The forward declaration only let's you use the type in certain ways, for instance, as a pointer. But some uses of an incomplete type aren't permited. For instance, you can't use sizeof(T) if T is incomplete. You can't define a variable of type T if T is incomplete. These rules make it possible for C++ translation unit to be compiled in one pass. By incomplete, I mena at that specific point in the source. Eventually the type gets fully defined. Other languages such as Java don't hav this restriction.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 0
    Last Post: 03-20-2008, 07:59 AM
  2. Replies: 28
    Last Post: 07-16-2006, 11:35 PM
  3. Compiler "Warnings"
    By Jeremy G in forum A Brief History of Cprogramming.com
    Replies: 24
    Last Post: 04-24-2005, 01:09 PM
  4. Errors
    By Rhidian in forum C Programming
    Replies: 10
    Last Post: 04-04-2005, 12:22 PM
  5. gcc problem
    By bjdea1 in forum Linux Programming
    Replies: 13
    Last Post: 04-29-2002, 06:51 PM