Thread: Assistance with templates

  1. #1
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654

    Assistance with templates

    If anyone could help me figure out WTH is going on here...
    Alright, so it's complicated templates.
    First, a snippet that shows where the problem occurs:
    Code:
    CCodeTokenGeneric* pToken = new CCodeTokenGeneric(CCodeToken::TOKEN_SPACE_INDENT);
    ppnew<CCodeTokenGeneric> pToken2(pToken);
    pp<CCodeToken/*Generic*/> pToken3(pToken2);
    The third line is where the problem occurs. The compiler complains that I cannot create an instance of the abstract base class CCodeToken:
    Code:
    class CCodeToken abstract
    Which by all means, it shouldn't be able to. However, that's not the problem, because I'm not instantiating an instance of the base class. I create a class derived from the base class, CCodeTokenGeneric:
    Code:
    class CCodeTokenGeneric: public CCodeToken
    The actual compile error is:
    Code:
    error C3622: 'CCodeToken': a class declared as 'abstract' cannot be instantiated
    see declaration of 'CCodeToken'
    see reference to class template instantiation 'CMemoryManagerNew<T>' being compiled
    with
    [
    	T=CCodeToken
    ]
    CMemoryManagerNew declaration is as follows:
    Code:
    template<typename T> class CMemoryManagerNew: public CMemoryManager<T>
    {
    public:
    	CMemoryManagerNew() throw(...);
    	CMemoryManagerNew(T* pNew) throw(...);
    	explicit CMemoryManagerNew(T NewValue) throw(...);
    	CMemoryManagerNew(const CMemoryManager<T>& rNew);
    	CMemoryManagerNew(const CMemoryManagerNew<T>& rNew);
    	CMemoryManagerNew(const CMemoryManagerNull& rNull);
    	CMemoryManagerNew(CMemoryManagerNull* pNull);
    	template<typename NewT> operator CMemoryManagerNew<NewT>& () const;
    	template<typename NewT> operator CMemoryManager<NewT>& () const;
    
    //protected:
    	//CMemoryManagerNew(CMemoryManagerNew<T>& rmm) throw(...) { }
    
    private:
    	CMemoryManagerNew(CMemoryManagerTimeCritical<T>&) { }
    	CMemoryManagerNew(CMemoryManagerTimeCriticalNew<T>&) { }
    	void operator = (CMemoryManagerTimeCritical<T>&) { }
    	void operator = (CMemoryManagerTimeCriticalNew<T>&) { }
    };
    The compile errors occurs on this line:
    Code:
    	explicit CMemoryManagerNew(T NewValue) throw(...);
    As to be expected. But what confuses me is that I do not have any code snippet that calls CMemoryManagerNew with type T = CCodeToken.
    As you can see from the example, I create a new instance of CCodeTokenGeneric, which works fine. Then I store it inside a ppnew (CMemoryManagerNew) which also works fine.
    But the problem comes when converting that CMemoryManagerNew to a CMemoryManager. This is expected to call the member function
    Code:
    	template<typename NewT> operator CMemoryManager<NewT>& () const;
    Which will return a reference to the same object but a different type. So it would return CMemoryManager<CCodeToken> so it can be embedded into the CMemoryManager object (pToken3).

    I know it fails in this function, since if I comment out the line
    Code:
    	explicit CMemoryManagerNew(T NewValue) throw(...);
    And run the code, it calls this function as it should.

    You might actually think that this is unsafe. That's why I use dynamic_cast internally to make sure the new type is compatible with the old. Here's the code for the
    Code:
    	template<typename NewT> operator CMemoryManager<NewT>& () const;
    Function:
    Code:
    return CMemoryManagerBase::TransformMemoryManager< NewT, CMemoryManager<NewT> >();
    Which calls:
    Code:
    	template<typename PtrType, typename FullType> FullType& TransformMemoryManager() const
    	{
    		PtrType* pTo = dynamic_cast<PtrType*>(p); // Security cast to make sure the new type in compatible with the old
    		ASSERT(pTo);
    		return *(FullType*)this;
    	}
    Any help would be appreciated.
    If anything is unclear, don't hesitate to ask.

    EDIT:
    Found the error.
    The TransformMemoryManager function returns a reference of type CMemoryManager, which makes the compiler parse CMemoryManager<CCodeType>, but CMemoryManager in turn also has a constructor that takes a CMemoryManagerNew<T>, so when the compiler parses that it becomes CMemoryManagerNew<CCodeToken> and so the compiler parses CMemoryManagerNew with type T = CCodeToken and finds the constructor CMemoryManagerNew(T New) which translates to CMemoryManagerNew(CCodeToken New) which is illegal since it's abstract.
    I guess to avoid headaches, I just remove the constructor. Any type can be initialized with its constructor anyway.
    Last edited by Elysia; 12-28-2007 at 01:08 PM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> But what confuses me is that I do not have any code snippet that calls CMemoryManagerNew with type T = CCodeToken
    The compiler is instantiating CMemoryManagerNew<T> with T = CCodeToken. Even if you don't have any code that invokes "explicit CMemoryManagerNew(T NewValue)", that constructor is still instantiated, which means T needs to be constructible (as you have it). The first solution that comes to mind is to change the constructor's signature to "T&" or "const T&", then T no longer needs to be constructible and an abstract base class can be used for T.

    gg

  3. #3
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I didn't see any code that instantiated CMemoryManagerNew with type T = CCodeToken. The only code I had was with type T = CCodeTokenGeneric. But I see the problem lied hidden inside the depths of the class code. The compiler isn't smart enough to actually point me to each class instantiation, which is kind of annoying since it caused all these headaches.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #4
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Quote Originally Posted by Elysia View Post
    The actual compile error is:
    Code:
    error C3622: 'CCodeToken': a class declared as 'abstract' cannot be instantiated
    see declaration of 'CCodeToken'
    see reference to class template instantiation 'CMemoryManagerNew<T>' being compiled
    with
    [
    	T=CCodeToken
    ]
    If you double click the red line, does it take you to the code where it's being instantiated? That would indeed be annoying if it didn't give any more clues as to *where* that instanciation was occuring

    gg

  5. #5
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Yeah, I know. First line points to
    Code:
    explicit CMemoryManagerNew(T NewValue) throw(...);
    Second line points to declaration of CCodeToken and the red line points to
    Code:
    pp<CCodeToken/*Generic*/> pToken3(pToken2);
    Which didn't really help.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Templates from DLL or static library problem
    By mikahell in forum C++ Programming
    Replies: 2
    Last Post: 01-01-2008, 01:49 AM
  2. Questions about Templates
    By Shamino in forum C++ Programming
    Replies: 4
    Last Post: 12-18-2005, 12:22 AM
  3. templates and inheritance problem
    By kuhnmi in forum C++ Programming
    Replies: 4
    Last Post: 06-14-2004, 02:46 AM
  4. When and when not to use templates
    By *ClownPimp* in forum C++ Programming
    Replies: 7
    Last Post: 07-20-2003, 09:36 AM