C++ Template object composition - How to initialize correctly?

Pages: 12
Hi guys!
This is my first time here, and i really need help!

I'm posting this because i'm having trobules in creating new data structures..

it may look weird but i would like to create a list of trees.

i created my Tree class, with a constructor like this:

template <class T> Tree<T>::Tree(Tree<T> *MyFather=NULL);
this constructor initializes the tree variables and sets a pointer to his father in his private area.

Now: i have my list, with this constructor:

template <class T> List<T>::List(int NElems,T Value);
which creates NElems elements with T Value.

My question is, how should i create a list of trees in my main function?

if i create it using this kind of instruction:

List<Tree<int> >Lista1(0,0);
Compiler gives me errors

The error given is:

[Error] no matching function for call to 'Tree<int>::Tree(Tree<int>)'

[LOOK THIS IMAGE TO GET MORE INFO]:
http://www84.zippyshare.com/v/EF9lXiCs/file.html
How can i fix this? Can you help me?
Last edited on
First of all, welcome to cplusplus.com :D

Your Tree Constructor takes a Tree<T>* (pointer)
Your List just gives the data a Tree<T> (no pointer)

Since you initalize it with 0 elements you could as well just write
List< Tree<int> > Lista1;
But the problem will reoccur when you try to insert values to the List.

One solution (and maybe the best, depending on implementation details) is to make a copy constructor in Tree.
1
2
3
4
5
Tree(const Tree<T>& otherTree)
{
    // copy data;
    this->father = otherTree.father;
}  
Last edited on
Thanks for your reply Gamer!

I already did the copy constructor for my tree structure, but i don't want it to get called, because my default constructor (with pointer) already does everything, and i need it to instance my ROOT.

I would like to declare in this way:

List<Tree<int>(NULL)> Lista1(0,0);

But i can't.


What do you suggest? :(
Show me the constructor of your list, that would help a lot
Good Morning gamer :)

So, we have my list with THIS constructor:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
template <class T> List<T>::List(int Elems,T Value2Assign) : ListCache(*this){
		
		//printf ("Costruttore Lista Chiamato.\n\n");
		Closing=false;
		NElems=0;
		SetFirstElement(NULL);
		SetLastElement(NULL);

		if (Elems>0){
			
			AddElement(LIST_START,1,Value2Assign);
			AddElement(LIST_END,Elems-1,Value2Assign);	
		}
	}



My List is composed by ListNodes, they follow this constructor:

1
2
3
4
5
template <class T> ListNode<T>::ListNode(T Value) : Value(Value){
		
		SetNextElement(NULL);
		SetPrevElement(NULL);
	}


Finally, my tree constructor has this code:

1
2
3
4
5
6
7
8
9
template <class T> Tree<T>::Tree(Tree<T> *MyFather):MyFather(MyFather){

		if (MyFather!=NULL){
			
			SetSonsLimit(MyFather->GetSonsLimit());
		}
		LastPosUsed=-8;
		
	}



My Problem is that my Value, located in the ListNode class, in this case is of Tree<int> Type.

and when i call it like this:

List<Tree<int> > MyList(0,NULL);

the meaning of this is that i want to create a list of 5 trees, every tree is a ROOT because has his father set to NULL (passed by my call).



My compiler says:
[Error] no matching function for call to 'Tree<int>::Tree(Tree<int>)'



how to fix this ? :(


EDIT:


something similar happens when i try to create my tree with simple integers inside:

Tree<int> MyTree;

Compiler says:

[Error] no matching function for call to 'List<Tree<int> >::List()'



My Tree has this private structure:

1
2
3
4
5
6
7
8
9
10
11
		
                    private:
			
			Tree<T> *MyFather;
			
			T Value;
			int LastPosUsed;
			static int SonsLimit;
			
			List<Tree<T> > Nodes;		 
	};



I really hope you can help me, i have an exam to pass with these :/ and i found no help searching on the net... Thank you and have a nice Sunday!
Last edited on
what does AddElement do?
I need to see the Line of code where you add the elements to your List.

Furthermore I just looked at the picture of the error Messages you posted and i realised that your copy constructor looks like this:
Tree(Tree<T>& other);
try changing it to
Tree(const Tree<T>& other);



Here is a small example of what you might want to have
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
template <typename T>
class List;

template <typename T>
class Tree
{
public:
	Tree(Tree<T>* father=nullptr, T value=T()) :
		_father(father),
		_value(value),
		_childs()
	{}

	T value() const { return _value; } // just to confirm the value

private:
	Tree<T>* _father;
	T _value;

	List < Tree<T> > _childs;
};

template <typename T>
class List
{
private:
	class Node
	{
	public:
		Node(Node* prev=nullptr, Node* next=nullptr, T value=T()) :
			prev(prev),
			next(next),
			value(value)
		{}

		Node* prev;
		Node* next;
		T value;
	};

public:
	List() : _first(nullptr) {}
	List(int count, T value)
	{
		if(count <= 0)
		{
			_first = nullptr;
			return;
		}

		_first = new Node(nullptr, nullptr, value); 
                _first->next = _first;
		_first->prev = _first;

		while(--count > 0)
		{
			Node* temp = new Node(_first->prev, _first, value);
			temp->prev->next = temp;
			temp->next->prev = temp;
		}
	}

	Node* nodes() const { return _first; } // just to confirm the value

private:
	Node* _first;
};

int main()
{
	List< Tree<int> > list(5, Tree<int>(nullptr, 5));
	List< Tree<int> > list2(5, 0);

	std::cout << list.nodes()->value.value() << std::endl; // just to confirm value
	std::cout << list2.nodes()->value.value() << std::endl; // just to confirm value


	return 0;
}
Last edited on
Hello gamer, still thanks for you help.

I didn't make my constructor with const because if i put it const, my compiler complains about receiving something that is not const...

is it a mistake to don't declare const the input reference in the copy constructor?


I looked this on your code:
T value=T()

and

childs(List<Tree<T>>())

what does this mean?

furthermore if i write this:

1
2
List< Tree<int> > list(5, Tree<int>(NULL));
List< Tree<int> > list2(5, 0);


My compiler returns this error:

[Error] no matching function for call to 'Tree<int>::Tree(Tree<int>)'
[Note] candidates are: Tree<T>::Tree(Tree<T>&) [with T = int]


by the way, here is my AddElement Function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
	template <class T> bool List<T>::AddElement(int Position, int N, T Value2Assign){
			
		bool ReturnValue=true;
		
		if (Position >=-3 && Position!=0 && (Position<= NElems || Position==1)){
			
			ListNode <T> *ElementAdded;	
			
			int Counter;
			for (Counter=0;Counter<N;Counter++){

				if (IsEmpty()){
					
					FirstElement=new ListNode<T>(Value2Assign);
					
					SetFirstElement(FirstElement);
					SetLastElement(FirstElement);
					
					LastElement->SetNextElement(NULL);
					
					FirstElement->SetPrevElement(NULL);
					
					ElementAdded=FirstElement;
					NElems++;
					ListCache.Set(0,NULL);
				}
				else if (Position==LIST_END || Position==GetNElems()){
					
					ListNode<T> *NewElement=new ListNode<T>(Value2Assign);
					
					LastElement->SetNextElement(NewElement);
					
					NewElement->SetPrevElement(LastElement);	
					
					SetLastElement(NewElement);
					
					ElementAdded=NewElement;
					NElems++;
					Position=LIST_END;
					ListCache.Refresh(ELEMS);
				}
				else if (Position==LIST_START || Position==1){
					
					ListNode<T> *NewElement=new ListNode<T>(Value2Assign);
					
					FirstElement->SetPrevElement(NewElement);
					
					NewElement->SetPrevElement(NULL);	
					NewElement->SetNextElement(FirstElement);
					
					SetFirstElement(NewElement);
					
					ElementAdded=NewElement;
					NElems++;
					Position=LIST_START;
					ListCache.Refresh(INDEXES_INCREMENT);	
				}
				else if (Position!=0){

					ListNode<T> *Element=this->SelectElement(Position-1);
					//&(*this)[Position-1];
					ListNode<T> *NewElement=new ListNode<T>(Value2Assign);	
					
				
					NewElement->SetPrevElement(Element->GetPrevElement());
					Element->GetPrevElement()->SetNextElement(NewElement);
					NewElement->SetNextElement(Element);
					Element->SetPrevElement(NewElement);
					
					ElementAdded=NewElement;
					NElems++;
					/*if (ListCache.GetLastStatus()==SET){
						
						ListCache.Refresh(ELEMS);	
					}*/
					//else ListCache.Refresh(INDEXES_INCREMENT);
					ListCache.Refresh(ELEMS);
				}
			}
		}
		else{
		
			ReturnValue=false;
		} 	

		//Order(ASC);
		return ReturnValue;
	}
Last edited on
I didn't make my constructor with const because if i put it const, my compiler complains about receiving something that is not const...

That should not happen.
It should only complain if you change the passed tree in the method.

is it a mistake to don't declare const the input reference in the copy constructor?

it is highly dangerous to do it.
Not declaring it const means the function may modify the passed argument

I looked this on your code:
T value=T()

and

childs(List<Tree<T>>())

what does this mean?

it means the value is default initialized

I'll answer to the rest later, i'm currently not at home
1
2
3
4
5
6
7
8
9
10
11
12
13
List(const List<T> &List2Copy) : ListCache(*this){
							
	NElems=0;
	SetFirstElement(NULL);
	SetLastElement(NULL);
				
	int Counter;
				
	for (Counter=0;Counter<List2Copy.GetNElems();Counter++){
					
		AddElement(LIST_END,1,List2Copy[Counter]);
	}
}


Look at this code, i can't set my List2Copy parameter to const because if i make it const, i can't use my operator[] which uses this code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
template <class T> T & List<T>::operator[](int Index){
		
		switch (Index){
			
			case -3:
				
				return (*(SelectElement(LIST_START))).GetValue();
			break;
			
			case 0:
				
				return (*(SelectElement(LIST_START))).GetValue();
			break;
			
			case -2:
				
				return (*(SelectElement(LIST_END))).GetValue();
			break;
			
			default:

				return (*(SelectElement(Index))).GetValue();
			break;
		}
	}


SelectElement is a method which calls other methods that modify my object status, so it's a chain, i can't make my object reference const because i use with it methods that could potentially modify its status.

will this be a problem? :(
will this be a problem? :(
Yeah but you can solve it ;)

The variable you modify is allowed to be modified in a const Method, right?
Then make the variable mutable! :D
1
2
3
4
5
6
7
8
9
10
class A
{
public:
    A() {_value = 5; }
    void changeValue() const { _value = 10; }
    void getValue() const { return _value; }
    
private:
    mutable int _value;
};


With that knowledge, make all Methods const that won't make any changes that are visible from outside.
const correctness is very important ;)
And since this might be the source of the problem, I think you understand what i mean ^^

The other way to solve the might-be problem might be changing the constructor to this, but it is not recommended since it copies the whole value (which might be a gigantic object!).
Tree(Tree<T> other); // -> pass by value


edit: back to the problem
So, i think you create the object in this line:
FirstElement=new ListNode<T>(Value2Assign);
or in one of those
ListNode<T> *NewElement=new ListNode<T>(Value2Assign);

I guess you ListNode Constructor looks something like this
ListNode(const T& value) : _value(value) { /*stuff*/ }
and not like this:
ListNode(T value) : _value(value) { /*stuff*/ }

So, here the problem comes.
You give ListNode a const T reference, (value is const and must not be changed!)
Now you call the constructor of Tree<T> where you pass a const T&
since you have no constructor that takes a const T& it searches for a constructor that takes the parameter by value, you haven't got that either.

So, your compiler knows that this is a const T& and in your Tree you just provide the implementation with T& as parameter, which might modify value and therefore is not an option because the value is const.

Note: all this is under the assumption that the ListNode takes a const T&
if it takes the parameter by value the problem is something else
Last edited on
REALLY THANK YOU FOR THE MUTABLE TYPE TRICK!! I didn't study it and didn't know its existence.

However, my ListNode gets created in this way:

ListNode(T Value=T());


I use operator= to assign same values, so there is no copy constructor.


Still thanks for your dedication :)
Last edited on
Yeah, I just stumpled over it a few weeks ago, but thats why we ask other ppl, right? ;)

Okey, then there is still one thing to tell you about whats going wrong.

Passing down your arguments looks like this when replacing all T with Tree<int>
List<Tree<int>> List(0, 0);

List(int cnt, Tree<int> value) { ... = new ListNode<Tree<int>>(value); }

ListNode(Tree<int> value) { ... = new Tree<int>(value); }

So, somewhere in your code you have to dynamically allocate memory and you call new Tree like above.
Notes: value is of type Tree<int> so which constructor do you call?
Answer: Tree(Tree<int>) OR Tree(const Tree<int>&) depending of which of them exist. but neither of them exist.

You have to make your copy constructor const correctly then it'll work
Last edited on
OK! I THINK I FOUND MY PROBLEM!

My constructor for the list was not the default, so my compiler wasn't able to find it, now i set my constructor to default with default variables with:

List(int NElems=0,T Value2Assign=T())

Now, my problem comes to the trees:


if i make my tree copy constructor with CONST, when i write this:

Tree<T> *Element2=&TreeToCopy;

compiler says:

[Error] invalid conversion from 'const Tree<int>*' to 'Tree<int>*'



and even if i don't use const, whenever i want to declare it with this code:

Tree<int> MyTree;

compiler says:
[Error] no matching function for call to 'Tree<int>::Tree(Tree<int>)'


but this happens only if i put in the private part of my tree class a List of trees.

this is my Tree class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
template <class T> class Tree{
		
		public:
			
			Tree(Tree<T> *MyFather=NULL);		
			
			Tree(Tree<T> &TreeToCopy);
			
			~Tree(){}
	
			Tree<T> &NewSon(int Mode=RIGHT, T Value=(T)0);
			Tree<T> &GetSon(int Position=LEFT) const;
	
			void Delete(int Mode, int SonPosition);
			void Import(int SonPosition,Tree<T> Tree2Import,int Mode);
			
			Tree<T> &SearchNode(T Value2Search) const;
			
			void SetValue(T Value);
			void SetHeight(int Value);
			T GetValue() const;
			int GetDeepness() const;
			int GetNElems() const;
			
			static int GetSonsLimit();
			static void SetSonsLimit(int Limit=BINARY);
			
			Tree<T> &GetFather() const;
			void SetFather(Tree<T> &Father);
			
			bool IsLastSon() const;
			bool IsFirstSon() const;
			void PreOrderView() const;
			void InOrderView() const;
			void PostOrderView() const;
			
			void SetLastPosUsed(int Pos);
			int GetLastPosUsed() const;
			
			const bool operator==(Tree<T> &TreeToCMP);

			const bool operator==(T ValueToCMP);
			const bool operator<(Tree<T> &TreeToCMP);
			const bool operator>(Tree<T> &TreeToCMP);
			const bool operator<=(Tree<T> &TreeToCMP);
			const bool operator>=(Tree<T> &TreeToCMP);
			const bool operator!=(Tree<T> &TreeToCMP);
			const Tree <T> &operator=(T Value);
			const Tree <T> &operator=(Tree<T> &TreeToCopy);
			
			T &operator[](int Index) const;
			Tree<T> &operator()(int Position) const;
			
		private:
			
			Tree<T> *MyFather;
			
			T Value;
			int LastPosUsed;
			static int SonsLimit;
			
			List<Tree<T> > Nodes;		 
	};


Any Ideas??? REALLY, REALLY, REALLY THANKS!
Last edited on
HOLY SHIT WHAT ARE YOU DOING
Tree<T> *Element2=&TreeToCopy;

When making a copy constructor you dont point to the other tree.
A CopyConstructor is to copy all data in tree without modifying it in any way.
You can be happy that the compiler gave you an error for this ^^
1
2
3
4
5
6
7
Tree(const Tree<T> &TreeToCopy)
{
    this->MyFather = TreeToCopy->MyFather;
    this->Value = TreeToCopy->Value;
    this->LastPosUsed = TreeToCopy->LastPosUsed;
    this->Nodes = TreeToCopy->Nodes;
}

or the more simple version (only available when the operator= is implemented)
1
2
3
4
Tree(const Tree<T> &TreeToCopy)
{
    *this = TreeToCopy; // the value of this tree is the value of TreeToCopy
}


make them const, you don't modify a tree when comparing.
at the moment you return a const bool ^^
1
2
3
4
5
6
7
			bool operator==(const Tree<T> &TreeToCMP) const;
		        bool operator==(const T& ValueToCMP) const;
			bool operator<(const Tree<T> &TreeToCMP) const;
			bool operator>(const Tree<T> &TreeToCMP) const;
			bool operator<=(const Tree<T> &TreeToCMP) const;
			bool operator>=(const Tree<T> &TreeToCMP) const;
			bool operator!=(const Tree<T> &TreeToCMP) const;

and change these things
1
2
3
4
5
			Tree <T> operator=(T Value); // don't return by reference
			Tree <T> operator=(Tree<T> &TreeToCopy); // don't return by reference

			const Tree<T>* const GetFather() const; // is a pointer so return it as one
			void SetFather(Tree<T>* Father); // Father is a pointer so pass it like one 


and even if i don't use const, whenever i want to declare it with this code:

Tree<int> MyTree;

compiler says:
[Error] no matching function for call to 'Tree<int>::Tree(Tree<int>)'


The problem here is in your list and BECAUSE you don't declare it const.
Somewhere in your list you call:
List(Tree<int> value) { ... = new Tree<int>(value); }
Note: value is a Tree<int>, so you call one of the following constructors:
Tree<int>(Tree<int>); or
Tree<int>(const Tree<int>&);

but neither of them is available, so your compiler complains about it.
Last edited on
Good morning gamer :).


I used pointers in copy constructor because i didn't want to use recursion, i wanted to make a loop that would have copied the whole tree without recursion...

i put const, and set mutable some attributes, but my program crashes just on the declaration of my tree, declared this way:

Tree<int> MyTree;

this is the code of my copy constructor:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
template <class T> Tree<T>::Tree(const Tree<T> &TreeToCopy) : MyFather(NULL){
				
		*this=TreeToCopy.GetValue();
		
		SetSonsLimit(TreeToCopy.GetSonsLimit());
					
		int Counter=0;
		int Depth=0;
		bool End=false;
		
		Tree<T> *Element=this;
		Tree<T> *Element2=const_cast<Tree<T>*>(&TreeToCopy);
		
		while (End==false && Element2->GetNElems()>0){
			
			Depth++; 
			
			if (Counter==0){
				
				Element->SetLastPosUsed(POS_UNDEFINED);
				Element2->SetLastPosUsed(POS_UNDEFINED);
				
				for (int i=0;i<Element2->GetNElems();i++){
					
					Element->NewSon(RIGHT,(*Element2)(NEXT).GetValue());
				}
				
				Element2->SetLastPosUsed(POS_UNDEFINED);
				Element->SetSonsLimit(Element2->GetSonsLimit());
				Counter=1;
			}
			
			(*Element)(NEXT);
			(*Element2)(NEXT);
			
			if ((*Element2)(LAST_USED).GetNElems()>0){
				
				Element=&(*Element)(LAST_USED);
				Element2=&(*Element2)(LAST_USED);
				Counter=0;
			}
			else{
								
				if (((*Element2)(LAST_USED).IsLastSon())){
					
					do{
						
						Depth--;
						if (&(*Element).GetFather()!=NULL && &(*Element2).GetFather()!=NULL&& Element2!=Element && Element2!=&TreeToCopy){
							
							Element=&(Element->GetFather());
							Element2=&(Element2->GetFather());	
						}
						Counter=1;
					}while ((*Element)(LAST_USED).IsLastSon() && &(*Element).GetFather()!=NULL && &(*Element).GetFather()!=&this->GetFather());
					
					if ((Element2==&TreeToCopy && ((*Element2)(LAST_USED).IsLastSon()))){
						
						End=true;	
					}
				}
				
				Depth--;
			}
		}	
	}



I know it could seem weird but it worked... before all this shit happened.

Shall i use recursion? is there a better way to do this? i didn't use recursion because i read that on large data sets recursion uses much resources than iteration, so i chose iteration.
Last edited on
Yeah, it is weird...

Whats wrong with just typing *this = TreeToCopy;?;
I mean, you implemented the assignment operator for trees, right?
my operator= uses the same loop.

but my program always crashes during instantiation of Tree object... :/
You love living risky right?
Tree<T> *Element2=const_cast<Tree<T>*>(&TreeToCopy);
Please explain to me in your own words what this line of code does.


Do you know what static means?
static int SonsLimit;

Furthermore I would use recursion here because you want to copy a tree, you never know how deep it is.

I know it could seem weird but it worked... before all this shit happened.

Well, what did you change?
And how do you know it worked?



but my program always crashes during instantiation of Tree object... :/
Did you try checking where it crashes?
Like debugging?
Or printing "Test" when it reached a certain point?


i put const, and set mutable some attributes, but my program crashes just on the declaration of my tree, declared this way:

Tree<int> MyTree;
Can you go in more detailed?
Like in which line of the constructor it crashes?

my operator= uses the same loop.
Try avoiding code duplication
Last edited on
with:
Tree<T> *Element2=const_cast<Tree<T>*>(&TreeToCopy);

i wanted to give element2 the non const type of &TreeToCopy.


Yes i know how static members work :)


when i debug my program crashes in the constructor, just on the first line, not the code itself but on the "definition" of the procedure.

it seems to work if i make my Nodes list of this type: List<Tree<T> *> Nodes.

I want it to become List<Tree<T> >Nodes;


:/
Last edited on
Tree<T> *Element2=const_cast<Tree<T>*>(&TreeToCopy);
i wanted to give element2 the non const type of &TreeToCopy.

Why make it non const?
Is there a reason why you have to make it non const?
if no then don't cast the const away.

Protip: pointers can be const in 2 different ways.
(The compiler reads them from right to left)
1. the value where you point to is const (const T*) (compiler: pointer to a const T)
2. the location where you point is const (T* const) (compiler: const pointer to a T)
and you can mix em
const location and const value: const T* const (const pointer to a const T)
In your case, you want to change the location where you point to but you don't modify the Object so you might want to just use const Tree<T>* Element;


Yes i know how static members work :)
SetSonsLimit(TreeToCopy.GetSonsLimit());
SonsLimit is the same in every tree, so you don't actually change anything there, neither does it here

1
2
3
4
5
		if (MyFather!=NULL){
			
			SetSonsLimit(MyFather->GetSonsLimit());
		}
		LastPosUsed=-8;



when i debug my program crashes in the constructor, just on the first line, not the code itself but on the "definition" of the procedure.

Uhm, can't you step inside the constructor? (i think f11? or f10?)

If it really crashes then you have some other problem.
Try calling all default constructors in the Tree constructor
1
2
3
4
5
6
7
8
9
10
11
12
template <class T> Tree<T>::Tree(Tree<T> *MyFather) : 
    MyFather(MyFather),
    Value(),
    LastPosUsed(-8),
    Nodes()    
{

		if (MyFather!=NULL){
			
			SetSonsLimit(MyFather->GetSonsLimit()); // does nothing 
		}
}
Last edited on
Pages: 12