LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 06-06-2007, 10:55 PM   #1
The_Nerd
Member
 
Registered: Aug 2002
Distribution: Debian
Posts: 540

Rep: Reputation: 32
Specialized template class constructors a headache...


Hello! I am still green around the ears when it comes to C++. I am having a problem with constructor templates. I know what the problem is, but I don't know the syntax required to fix it. I want to use the templatized version of the class constructor when ANY data type but CTypeContainer is used, code (problematic parts marked in red):

Code:
namespace Ner2D
{
	namespace Types
	{
		class CTypeBase
		{
			public:
				virtual CTypeBase *Me() = 0;
		};
		
		template <typename T>
		class CTypeContainerBase : public CTypeBase
		{
			public:
				T Data;
				
				CTypeContainerBase *Me() { return this; }
				
				CTypeContainerBase(const T &D)
				{
					Data = D;
				}
				
				T &operator=(const T &D)
				{
					Data = D;
					
					return D;
				}
		};
		
		class CTypeContainer
		{
			public:
				template <typename T> T &operator=(const T &Data)
				{
					cout << "Assigning right now!\n";
					if (pData != NULL) delete pData->Me();
					pData = new CTypeContainerBase<T>(Data);
					TypeString = typeid(T).name();
					return ((CTypeContainerBase<T> *)pData)->Data;
				}
				
				template <typename T> CTypeContainer(const T &Data)
				{
					cout << "Creating2\n";
					pData = NULL;
					(*this) = Data;
				}
				
				CTypeContainer() { cout << "Creating1\n"; pData = NULL; }
				~CTypeContainer()
				{
					if (pData != NULL)
					{
						delete pData->Me();
						pData = NULL;
					}
				}
				
				template <typename T> T &Object()
				{
					if (pData == NULL) THROW("No object contained in container");
					return ((CTypeContainerBase<T> *)pData)->Data;
				}
			private:
				CTypeBase *pData;
				string TypeString;
				
		};
		
		template <> CTypeContainer &CTypeContainer::operator=<CTypeContainer>(const CTypeContainer &Cont)
		{
			pData = Cont.pData;
			TypeString = Cont.TypeString;
		}
		
		template <> CTypeContainer::CTypeContainer<CTypeContainer>(const CTypeContainer &Data)
		{
			(*this) = Data;
		}
	}
}
This throws compiler errors:
Code:
[th317erd@TheNerd Ner2D]$ make
g++ -g -O2 -Iinclude/ -c source/ner2d.cpp -o source/ner2d.o
In file included from include/event.h:5,
                 from include/ner2d.h:10,
                 from source/ner2d.cpp:1:
include/n2d_types.h:88: error: `Ner2D::Types::CTypeContainer' is not a template
include/n2d_types.h:88: error: expected unqualified-id before "const"
include/n2d_types.h:88: error: expected `)' before "const"
include/n2d_types.h:88: error: expected `;' before "const"
make: *** [source/ner2d.o] Error 1
I know that it is complaining because it thinks I am trying to overload the CTypeContainer() (without arguments) constructor, which isn't a template. I don't know how to tell it WHICH constructor to overload. Help?

Last edited by The_Nerd; 06-06-2007 at 10:57 PM.
 
Old 06-07-2007, 06:18 PM   #2
dmail
Member
 
Registered: Oct 2005
Posts: 970

Rep: Reputation: Disabled
I started to edit your source The_Nerd and realised what it potential is and problems which are deeper.
I'm guessing you are wanting this to use for containers to any type of object, would this also include pointers? if so this would create problems if they were classes to polymorhpic types themselves.
Your copy operator would cause splicing of the classes and would be much better implemented as a "copy"/"clone" function as to avoid this. I was also a little confused why you were returing the this pointer to delete it? It would be better to give the base (very base) class a virtual destructor (which it should have anyway) and then just delete the pData in CTypeContainer.

Classes should use the initialisation list.
You need to check the type requested by Object is the correct type.
Then there is the point that there is no need to call if(pointer)delete pointer as its safe in C++ to delete a null pointer.

This sounds like I'm ripping it apart but that is not the intention, as you can see there many things which could go wrong with your implementation.

"I am still green around the ears when it comes to C++"
This actually surprised me as what you are trying is so close to Boost::Any that its quite remarkable.
I would suggest that if this is for anything other than practice, to use or at least look at how boost has done this as it is a stable set of classes(using internal classes). You maybe able to just include the header as you can with some boost files I'm not sure.

http://www.boost.org/doc/html/any.html
http://www.boost.org/boost/any.hpp
 
Old 06-07-2007, 06:26 PM   #3
The_Nerd
Member
 
Registered: Aug 2002
Distribution: Debian
Posts: 540

Original Poster
Rep: Reputation: 32
Why is this invalid?:

Code:
class CTypeContainer
{
	public:
		...blah

		
		template <typename T> CTypeContainer(const T &Data)
		{
			pData = NULL;
			(*this) = Data;
		}
				
		template <> CTypeContainer<CTypeContainer>(const CTypeContainer &Cont)
		{
			(*this) = Cont;
		}

      ...blah
}
Output:

Code:
[th317erd@TheNerd Ner2D]$ make
g++ -g -O2 -Iinclude/ -c source/ner2d.cpp -o source/ner2d.o
In file included from include/event.h:5,
                 from include/ner2d.h:10,
                 from source/ner2d.cpp:1:
include/n2d_types.h:61: error: invalid explicit specialization before '>' token
include/n2d_types.h:61: error: explicit specialization in non-namespace scope `class Ner2D::Types::CTypeContainer'
include/n2d_types.h:61: error: `Ner2D::Types::CTypeContainer' is not a template
include/n2d_types.h:61: error: expected unqualified-id before "const"
include/n2d_types.h:61: error: expected `)' before "const"
include/n2d_types.h:61: error: expected `;' before "const"
In file included from include/ner2d.h:10,
                 from source/ner2d.cpp:1:
include/event.h: In constructor `Ner2D::Event::CEvent::CEvent()':
include/event.h:28: error: no matching function for call to `Ner2D::Types::CTypeContainer::CTypeContainer()'
include/n2d_types.h:43: note: candidates are: Ner2D::Types::CTypeContainer::CTypeContainer(const Ner2D::Types::CTypeContainer&)
include/event.h: In copy constructor `Ner2D::Event::CEvent::CEvent(const Ner2D::Event::CEvent&)':
include/event.h:30: error: no matching function for call to `Ner2D::Types::CTypeContainer::CTypeContainer()'
include/n2d_types.h:43: note: candidates are: Ner2D::Types::CTypeContainer::CTypeContainer(const Ner2D::Types::CTypeContainer&)
make: *** [source/ner2d.o] Error 1
[th317erd@TheNerd Ner2D]$

Last edited by The_Nerd; 06-07-2007 at 06:28 PM.
 
Old 06-07-2007, 06:40 PM   #4
dmail
Member
 
Registered: Oct 2005
Posts: 970

Rep: Reputation: Disabled
one is a copy constructor which the compiler will still generate and one is a conversion . Try:
template <typename T> CTypeContainer(const T &Data)
{
pData = NULL;
(*this) = Data;
}

CTypeContainer(const CTypeContainer &Cont)
{
(*this) = Cont;
}
 
Old 06-07-2007, 06:40 PM   #5
The_Nerd
Member
 
Registered: Aug 2002
Distribution: Debian
Posts: 540

Original Poster
Rep: Reputation: 32
Quote:
Originally Posted by dmail
I started to edit your source The_Nerd and realised what it potential is and problems which are deeper.
I'm guessing you are wanting this to use for containers to any type of object, would this also include pointers? if so this would create problems if they were classes to polymorhpic types themselves.
Your copy operator would cause splicing of the classes and would be much better implemented as a "copy"/"clone" function as to avoid this. I was also a little confused why you were returing the this pointer to delete it? It would be better to give the base (very base) class a virtual destructor (which it should have anyway) and then just delete the pData in CTypeContainer.

Classes should use the initialisation list.
You need to check the type requested by Object is the correct type.
Then there is the point that there is no need to call if(pointer)delete pointer as its safe in C++ to delete a null pointer.

This sounds like I'm ripping it apart but that is not the intention, as you can see there many things which could go wrong with your implementation.

"I am still green around the ears when it comes to C++"
This actually surprised me as what you are trying is so close to Boost::Any that its quite remarkable.
I would suggest that if this is for anything other than practice, to use or at least look at how boost has done this as it is a stable set of classes(using internal classes). You maybe able to just include the header as you can with some boost files I'm not sure.

http://www.boost.org/doc/html/any.html
http://www.boost.org/boost/any.hpp
Thanks for the feedback dmail! I see what you are saying about the deleting/returning this. You are right, I didn't think about that, I will implement it. I am not using Boost because it is bloated. Besides, since I am still learning a C++, I'd like to figure it out on my own (with the help of the kind people here at LQ.com of course ). The reason this set of classes is such a headache is that I cannot have the type forced when the intance of the object is being created (that would just be a simple template). With what I am doing (an event stack), the object must be able to be created without any type being contained/forced during creation, and then be able to contain any type later on. I am almost there! I just have this one bug to work out, and it should work fine. By the way, this should work for any data type, including pointers, because if you'll notice, it DOES create a copy of the object, and duplicates it exactly.


"You need to check the type requested by Object is the correct type."

I was already planning this, that is why I have "typeid" assigned to TypeString. I'll use this later on (after I fix this current bug), to check and make sure the types match when the user asks for the data contained.

"Then there is the point that there is no need to call if(pointer)delete pointer as its safe in C++ to delete a null pointer."

Thanks! I didn't know that.

"This sounds like I'm ripping it apart but that is not the intention, as you can see there many things which could go wrong with your implementation"

No problem! I am here to learn, and any pointers on anything, no matter how harsh, be assured I'll be paying humble grateful attention.
 
Old 06-07-2007, 06:44 PM   #6
The_Nerd
Member
 
Registered: Aug 2002
Distribution: Debian
Posts: 540

Original Poster
Rep: Reputation: 32
Quote:
Originally Posted by dmail
one is a copy constructor which the compiler will still generate and one is a conversion . Try:
template <typename T> CTypeContainer(const T &Data)
{
pData = NULL;
(*this) = Data;
}

CTypeContainer(const CTypeContainer &Cont)
{
(*this) = Cont;
}
Thanks so much! That worked out just fine... though I am still having a bug. I'll track down the other bug, and let you know the results!
 
Old 06-07-2007, 06:46 PM   #7
dmail
Member
 
Registered: Oct 2005
Posts: 970

Rep: Reputation: Disabled
Quote:
By the way, this should work for any data type, including pointers, because if you'll notice, it DOES create a copy of the object, and duplicates it exactly.
Ok look at the copy constructor in CTypeContainerBase.
If there is classes such as
class a{}
class b: public a{}
class c: public b{}

And the T is an a* when the copy operator is invoked what will happen?

edit
Quote:
I was already planning this, that is why I have "typeid" assigned to TypeString. I'll use this later on (after I fix this current bug), to check and make sure the types match when the user asks for the data contained.
This is not the correct approach as you can see for boost any the classes return type_info, using the type name is bound to get you into problems as names are not guaranteed to be unique for a type.


Quote:
the object must be able to be created without any type being contained/forced during creation, and then be able to contain any type later on
Code:
    any()
          : content(0)
        {
        }
code

Last edited by dmail; 06-07-2007 at 06:55 PM.
 
Old 06-07-2007, 11:54 PM   #8
The_Nerd
Member
 
Registered: Aug 2002
Distribution: Debian
Posts: 540

Original Poster
Rep: Reputation: 32
Quote:
Originally Posted by dmail
Code:
    any()
          : content(0)
        {
        }
code
What? What I meant, is I can't have the type set via a template parameter, as that would require a set type at variable definition.
 
Old 06-08-2007, 07:13 AM   #9
dmail
Member
 
Registered: Oct 2005
Posts: 970

Rep: Reputation: Disabled
Quote:
Originally Posted by The_Nerd
What? What I meant, is I can't have the type set via a template parameter, as that would require a set type at variable definition.
I'm sorry I don't quite follow what you are getting at.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
$#^!% template specialization headache! The_Nerd Programming 3 04-27-2007 03:45 PM
c++ class template doesn't work!! tagigogo Programming 2 11-02-2005 04:45 PM
Template class with a template member... Nicholas Bishop Programming 3 02-21-2005 08:27 PM
template class ckcheung0927 Programming 3 11-28-2004 03:59 PM
C++ - throwing exceptions in derived class constructors? MadCactus Programming 4 08-09-2004 06:29 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 02:36 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration