11 Replies - 2165 Views - Last Post: 19 July 2012 - 06:43 PM Rate Topic: -----

#1 leeto  Icon User is offline

  • New D.I.C Head

Reputation: -3
  • View blog
  • Posts: 38
  • Joined: 17-June 12

static variable and function with <template>

Posted 18 July 2012 - 07:57 AM

I try to create small project in order to better understand how key word static works with templates . However some compiles errors crush my plan. Could you help me resolve compile errors:


1>------ Build started: Project: 4.2b - Ex 1. Static Variable for Array Def Size. Templates, Configuration: Release Win32 ------
1> main.cpp
1>c:\all my\с++\ha level 6\solution level 6\solution level 6\4.2b - ex1. static variable for array def size. templates\array.cpp(40): error C2724: 'Array<Type>::DefaultSize' : 'static' should not be used on member functions defined at file scope
1> with
1> [
1> Type=int
1> ]
1> c:\all my\с++\ha level 6\solution level 6\solution level 6\4.2b - ex1. static variable for array def size. templates\array.cpp(40) : while compiling class template member function 'void Array<Type>::DefaultSize(int)'
1> with
1> [
1> Type=int
1> ]
1> main.cpp(77) : see reference to class template instantiation 'Array<Type>' being compiled
1> with
1> [
1> Type=int
1> ]
1>c:\all my\с++\ha level 6\solution level 6\solution level 6\4.2b - ex1. static variable for array def size. templates\array.cpp(32): error C2724: 'Array<Type>::DefaultSize' : 'static' should not be used on member functions defined at file scope
1> with
1> [
1> Type=int
1> ]
1> c:\all my\с++\ha level 6\solution level 6\solution level 6\4.2b - ex1. static variable for array def size. templates\array.cpp(32) : while compiling class template member function 'int Array<Type>::DefaultSize(void)'
1> with
1> [
1> Type=int
1> ]
1>c:\all my\с++\ha level 6\solution level 6\solution level 6\4.2b - ex1. static variable for array def size. templates\array.cpp(32): error C2724: 'Array<Type>::DefaultSize' : 'static' should not be used on member functions defined at file scope
1> with
1> [
1> Type=double
1> ]
1> c:\all my\с++\ha level 6\solution level 6\solution level 6\4.2b - ex1. static variable for array def size. templates\array.cpp(32) : while compiling class template member function 'int Array<Type>::DefaultSize(void)'
1> with
1> [
1> Type=double
1> ]
1> main.cpp(79) : see reference to class template instantiation 'Array<Type>' being compiled
1> with
1> [
1> Type=double
1> ]
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========


//array.h
#ifndef Array_H
#define Array_H

template <class Type> //Remove the "=double" default parameter.
class Array
{
private:
  int m_size;
  Type* m_data; //m_data should be a pointer, since you want to allocate data to it
 // static int m_size_default;

//protected : 
	//static int m_size_default;

public:

static int m_size_default;
  Array();
  Array(int new_size);
  Array(const Array<Type>& ar);
  ~Array(); //Don't make your destructor virtual. There is no reason to do it.

  // Selectors 
  int Size() const {return m_size;};
  static int DefaultSize();
  static void DefaultSize(int newSize) ;
  

  const Type& Array<Type>::GetElement(int index) const;
  void Array<Type>::SetElement(const Type& type_object, int index);
  Array<Type>& operator=(const Array& ar); //Const correctness here.
  Type& Array<Type>::operator [] (int index);
  void Swap(Array& ar);  
};



#endif

// ****************

//point.h

#include "array.h"
#include <sstream>
#include <iostream>
using namespace std;


class Point
{
private:
    double m_x;                                
    double m_y;                                
public:
    // Constructors
    Point(): m_x(0), m_y(0) {};                            
	Point(double new_x, double new_y) : m_x(new_x), m_y(new_y) {};
	friend ostream& operator << (ostream& os, const Point& point)
{
    return os << point.ToString();
}
	std::string Point::ToString(void) const                // create a string representation of a point
{
// create a string like: “Point(1.5, 3.9)”
      std::ostringstream os;
    os << m_x << " , " << m_y;
    std::string double_string = os.str();
 
    return "Point(" + double_string + ")";
}
};

//*****************

//array.cpp
#include "Array.h"
#include <sstream>
#include <iostream>
#include <exception>
using namespace std;
#ifndef Array_CPP
#define Array_CPP



template<class T>
int Array<T>::m_size_default = 10;

// default constructor 
template <typename T>
Array<T>::Array()
{

m_data = new T[m_size_default];
 
// iterate through array
for(int i=0; i<m_size_default; i++)
{
T temp;
m_data[i] = temp;
}
}

template <typename T>
static int Array<T>::DefaultSize() 
{ // line 32 
	
	return m_size_default;
}


template <typename T>
  static void Array<T>::DefaultSize(int newSize) 
  { // line 40 
	  m_size_default = newSize; 
	  
  };


template <class Type>
Array<Type>::Array(int new_size) : m_size(new_size), m_data(new Type[new_size])
{ }

template <class Type>
Array<Type>::~Array()
{
  //Technically, the if is not necessary
  if(m_data)
  {
    delete[] m_data;
    m_data = 0;
  }

  //Not necessary either, but just to be clean
  m_size = 0;
}

template <class Type>
Array<Type>::Array(const Array& ar) : m_data(0), m_size(0)
{
  if(!ar.m_data) {return;}

  Array tmp; //Copy construct into another temporary array, this way, if something throws, tmp will clean itself up.

  //Create the array
  tmp.m_data = new Type[ar.m_size];
  tmp.m_size = ar.m_size;

  //Copy the array elements
  for(int i = 0; i < tmp.m_size; ++i)
    {tmp.m_data[i] = ar.m_data[i];}

  //All done! swap into this!
  this->Swap(tmp);
}

template <class Type>
Array<Type>& Array<Type>::operator=(const Array& ar)
{
  //Check self assign:
  if(this == &ar) {return *this;}

  Array<Type> copy(ar); //Create a copy of ar; If this fails, then *this will not be changed, and nothing will leak

  //Succeeded creating copy. Now we can put it inside this
  this->Swap(copy); //And then swap the copy into this!

  return *this;
}

template <class Type>
void Array<Type>::Swap(Array& ar)
{
  Type* data = m_data;
  int   size = m_size;
  m_data = ar.m_data;
  m_size = ar.m_size;
  ar.m_data = data;
  ar.m_size = size;
}

template <class Type> 
void Array<Type>::SetElement(const Type& type_object, int index)
{

		if (index >= m_size || index < 0 )
		{ throw std:: out_of_range ("out of range error in void Array<Type>::SetElement");}
		m_data[index] = type_object;
		cout << "Set Element " << type_object  << endl;

	
}
template <class Type> 
const Type& Array<Type>::GetElement(int index) const
{
	
		if (index >= m_size || index < 0)
		{ throw std::out_of_range ("Out of range error in void Array<Type>::GetElement");} 

	return m_data[index];
}
template <class Type> 
Type& Array<Type>::operator [] (int index) 
{
    cout << "Array [] operator" << endl;
 
    if (index >= this->m_size)
	{
        cout << "i am hreeeee" << endl;
        return this->m_data[0];
	}
    return m_data[index];
}



#endif //Array_CPP

// ************ 




/*
Exercise 1: Static Variable for Array Default Size (optional)

Static variables, which are shared between all instances of a class, 
behave slightly different with templates. We are going to test this with a static variable in 
the Array class that indicates the default array size when using the default constructor.
Add a static data member to the Array class indicating the default size.
Initialise this static in the source file to a value.
Also add static functions to set and get the default size.
In the default constructor, use the static default size variable 
instead of a literal value to set the array size.
Test the following code in the main program:
Code (cpp):
Array<int> intArray1;
Array<int> intArray2;
Array<double> doubleArray;
 
cout<<intArray1.DefaultSize()<<endl;
cout<<intArray2.DefaultSize()<<endl;
cout<<doubleArray.DefaultSize()<<endl;
 
intArray1.DefaultSize(15);
 
cout<<intArray1.DefaultSize()<<endl;
cout<<intArray2.DefaultSize()<<endl;
cout<<doubleArray.DefaultSize()<<endl;
What values are printed? Can you explain the result?
*/
//
//
// QuantNet C++ course
// LEVEL 6. 4.2b - Advanced Templates
// https://www.quantnet.com/threads/level-6-homework.7857/
// Exercise 1: Static Variable for Array Default Size (optional)
//
// Created by Denis Igoshev
//
// additional helping links: 
// https://www.quantnet.com/threads/4-2b-exercise-1.9082/
// 

//main.cpp
		#include "point.h"
		#include <iostream>
		#include "array.cpp"
		#include <exception>
		using namespace std;

int main()
{
	Array<int> intArray1;
    Array<int> intArray2;
    Array<double> doubleArray;
 
    cout<<intArray1.DefaultSize()<<endl;
    cout<<intArray2.DefaultSize()<<endl;
    cout<<doubleArray.DefaultSize()<<endl; // line 57 
 
    intArray1.DefaultSize(15);
   
    cout<<intArray1.DefaultSize()<<endl;
    cout<<intArray2.DefaultSize()<<endl;
    cout<<doubleArray.DefaultSize()<<endl;
	
}


many thanks in advance

Is This A Good Question/Topic? 0
  • +

Replies To: static variable and function with <template>

#2 vividexstance  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 660
  • View blog
  • Posts: 2,270
  • Joined: 31-December 10

Re: static variable and function with <template>

Posted 18 July 2012 - 08:01 AM

templates don't affect what the keyword static means in C++. You can have static functions or static variables. Don't get confused when someone says statically allocated variables, all that means is that the variables are just regularly declared variables most likely on the program's runtime stack.

*EDIT*: Here's a quick suggestion. When writing a class template, first write the class as a regular class and test it thoroughly until you're confident there are no bugs, After that, it's fairly simple to change the regular class to a class template. Just remember when you're defining the regular class that the definition should all be in the header file.

*EDIT2*: When defining the static member functions, you don't copy over the static keyword. So on lines 107 and 115 and any where else you define a static member function, just delete the static keyword.

This post has been edited by vividexstance: 18 July 2012 - 08:07 AM

Was This Post Helpful? 0
  • +
  • -

#3 jimblumberg  Icon User is offline

  • member icon


Reputation: 4071
  • View blog
  • Posts: 12,557
  • Joined: 25-December 09

Re: static variable and function with <template>

Posted 18 July 2012 - 08:18 AM

First when you are defining your class you do not use the class scope operator. For instance in your class definition you have:
class Array
{
public:

  const Type& Array<Type>::GetElement(int index) const;
  void Array<Type>::SetElement(const Type& type_object, int index);

You need to remove the Array<Type>:: from these lines.

Next C/C++ is case sensitive, even if your underlying operating system is not. So when you include the following include files:
#include <Array.h>
#include <array.h>

C/C++ will treat these as different files, even if your operating system doesn't, this may cause problems.

Next never include .cpp files, use the "using namespace std;" directive in a header file. And remember that when dealing with templates both the implementation and the definition must be in the same compilation unit. This usually means the same file. Quite often template implementations will be header only implementations, meaning there is no .cpp file. It is possible to "include" the implementation in your header by using the #include pre-processor directive. But if you do this then I suggest you rename your implementation to something other than .cpp. Maybe something like .inc. Also this inclusion must be after the class definition:

//array.h
#ifndef Array_H
#define Array_H

template <class Type> //Remove the "=double" default parameter.
class Array
{
......
};

#include "array.inc"

#endif


And this file must only be included by the include file that defines the class. And this inclusion should be protected by the header file's include guards.

By the way I recommend, until you are more familiar with the language, that you place everything inside one header file.

Jim

This post has been edited by jimblumberg: 18 July 2012 - 08:19 AM

Was This Post Helpful? 1
  • +
  • -

#4 leeto  Icon User is offline

  • New D.I.C Head

Reputation: -3
  • View blog
  • Posts: 38
  • Joined: 17-June 12

Re: static variable and function with <template>

Posted 19 July 2012 - 08:22 AM

View Postjimblumberg, on 18 July 2012 - 08:18 AM, said:

First when you are defining your class you do not use the class scope operator. For instance in your class definition you have:
class Array
{
public:

  const Type& Array<Type>::GetElement(int index) const;
  void Array<Type>::SetElement(const Type& type_object, int index);

You need to remove the Array<Type>:: from these lines.

Next C/C++ is case sensitive, even if your underlying operating system is not. So when you include the following include files:
#include <Array.h>
#include <array.h>

C/C++ will treat these as different files, even if your operating system doesn't, this may cause problems.

Next never include .cpp files, use the "using namespace std;" directive in a header file. And remember that when dealing with templates both the implementation and the definition must be in the same compilation unit. This usually means the same file. Quite often template implementations will be header only implementations, meaning there is no .cpp file. It is possible to "include" the implementation in your header by using the #include pre-processor directive. But if you do this then I suggest you rename your implementation to something other than .cpp. Maybe something like .inc. Also this inclusion must be after the class definition:

//array.h
#ifndef Array_H
#define Array_H

template <class Type> //Remove the "=double" default parameter.
class Array
{
......
};

#include "array.inc"

#endif


And this file must only be included by the include file that defines the class. And this inclusion should be protected by the header file's include guards.

By the way I recommend, until you are more familiar with the language, that you place everything inside one header file.

Jim


Those were very helpful comments I really appreciated... but what about my correct problem belong to static ?
I 100 % sure that what you advised don't re-solve my problem because current project I built up by using old one that work fine. I just add static variable that's all

This post has been edited by leeto: 19 July 2012 - 08:25 AM

Was This Post Helpful? 0
  • +
  • -

#5 jimblumberg  Icon User is offline

  • member icon


Reputation: 4071
  • View blog
  • Posts: 12,557
  • Joined: 25-December 09

Re: static variable and function with <template>

Posted 19 July 2012 - 08:30 AM

Did you implement the changes I suggested?

What are you actually trying to accomplish by trying to make your functions static?

Jim
Was This Post Helpful? 1
  • +
  • -

#6 vividexstance  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 660
  • View blog
  • Posts: 2,270
  • Joined: 31-December 10

Re: static variable and function with <template>

Posted 19 July 2012 - 08:43 AM

Did you read the "*EDIT2* part of my comment?
Was This Post Helpful? 1
  • +
  • -

#7 leeto  Icon User is offline

  • New D.I.C Head

Reputation: -3
  • View blog
  • Posts: 38
  • Joined: 17-June 12

Re: static variable and function with <template>

Posted 19 July 2012 - 08:52 AM

View Postvividexstance, on 19 July 2012 - 08:43 AM, said:

Did you read the "*EDIT2* part of my comment?


Yes I read...

Update of code :
//array.h
#ifndef Array_H
#define Array_H

using namespace std;

template <class Type> //Remove the "=double" default parameter.
class Array
{
private:
  int m_size;
  Type* m_data; //m_data should be a pointer, since you want to allocate data to it
//  static int m_size_default;

//protected : 
	//static int m_size_default;

public:

  static int m_size_default; // line 20 
  Array();
  Array(int new_size);
  Array(const Array<Type>& ar);
  ~Array(); //Don't make your destructor virtual. There is no reason to do it.

  // Selectors 
  int Size() const {return m_size;};
  static int DefaultSize();
  static void DefaultSize(int newSize);
  

  const Type& GetElement(int index) const;
  void SetElement(const Type& type_object, int index);
  Array<Type>& operator=(const Array& ar); //Const correctness here.
  Type& operator [] (int index);
  void Swap(Array& ar);  
};



#endif

//array.cpp
#include "Array.h"
#include <sstream>
#include <iostream>
#include <exception>
using namespace std;
#ifndef Array_CPP
#define Array_CPP

template<class Type> // line 10 
int Array<int>::m_size_default = 10; // line 11

template<class Type> // line 13
int Array<double>::m_size_default = 10;

// default constructor 
	template <typename Type>
	Array<Type>::Array()
		{

	m_data = new Type[m_size_default];
 
			// iterate through array
			for(int i=0; i<m_size_default; i++)
				{
					Type temp;
					m_data[i] = temp;
				}
		}
template <typename Type>
 int Array<Type>::DefaultSize() 
{ // line 32 
	
	return m_size_default;
}


template <typename Type>
   void Array<Type>::DefaultSize(int newSize)//: m_size_default(newSize)
  { // line 40 
	 m_size_default = newSize; 
	  
  }


template <class Type>
Array<Type>::Array(int new_size) : m_size(new_size), m_data(new Type[new_size])
{ }

template <class Type>
Array<Type>::~Array()
{
  //Technically, the if is not necessary
  if(m_data)
  {
    delete[] m_data;
    m_data = 0;
  }

  //Not necessary either, but just to be clean
  m_size = 0;
}

template <class Type>
Array<Type>::Array(const Array& ar) : m_data(0), m_size(0)
{
  if(!ar.m_data) {return;}

  Array tmp; //Copy construct into another temporary array, this way, if something throws, tmp will clean itself up.

  //Create the array
  tmp.m_data = new Type[ar.m_size];
  tmp.m_size = ar.m_size;

  //Copy the array elements
  for(int i = 0; i < tmp.m_size; ++i)
    {tmp.m_data[i] = ar.m_data[i];}

  //All done! swap into this!
  this->Swap(tmp);
}

template <class Type>
Array<Type>& Array<Type>::operator=(const Array& ar)
{
  //Check self assign:
  if(this == &ar) {return *this;}

  Array<Type> copy(ar); //Create a copy of ar; If this fails, then *this will not be changed, and nothing will leak

  //Succeeded creating copy. Now we can put it inside this
  this->Swap(copy); //And then swap the copy into this!

  return *this;
}

template <class Type>
void Array<Type>::Swap(Array& ar)
{
  Type* data = m_data;
  int   size = m_size;
  m_data = ar.m_data;
  m_size = ar.m_size;
  ar.m_data = data;
  ar.m_size = size;
}

template <class Type> 
void Array<Type>::SetElement(const Type& type_object, int index)
{

		if (index >= m_size || index < 0 )
		{ throw std:: out_of_range ("out of range error in void Array<Type>::SetElement");}
		m_data[index] = type_object;
		cout << "Set Element " << type_object  << endl;

	
}
template <class Type> 
const Type& Array<Type>::GetElement(int index) const
{
	
		if (index >= m_size || index < 0)
		{ throw std::out_of_range ("Out of range error in void Array<Type>::GetElement");} 

	return m_data[index];
}
template <class Type> 
Type& Array<Type>::operator [] (int index) 
{
    cout << "Array [] operator" << endl;
 
    if (index >= this->m_size)
	{
        cout << "i am hreeeee" << endl;
        return this->m_data[0];
	}
    return m_data[index];
}



#endif //Array_CPP

/*
Exercise 1: Static Variable for Array Default Size (optional)

Static variables, which are shared between all instances of a class, 
behave slightly different with templates. We are going to test this with a static variable in 
the Array class that indicates the default array size when using the default constructor.
Add a static data member to the Array class indicating the default size.
Initialise this static in the source file to a value.
Also add static functions to set and get the default size.
In the default constructor, use the static default size variable 
instead of a literal value to set the array size.
Test the following code in the main program:
Code (cpp):
Array<int> intArray1;
Array<int> intArray2;
Array<double> doubleArray;
 
cout<<intArray1.DefaultSize()<<endl;
cout<<intArray2.DefaultSize()<<endl;
cout<<doubleArray.DefaultSize()<<endl;
 
intArray1.DefaultSize(15);
 
cout<<intArray1.DefaultSize()<<endl;
cout<<intArray2.DefaultSize()<<endl;
cout<<doubleArray.DefaultSize()<<endl;
What values are printed? Can you explain the result?
*/
//
//
// QuantNet C++ course
// LEVEL 6. 4.2b - Advanced Templates
// https://www.quantnet.com/threads/level-6-homework.7857/
// Exercise 1: Static Variable for Array Default Size (optional)
//
// Created by Denis Igoshev
//
// additional helping links: 
// https://www.quantnet.com/threads/4-2b-exercise-1.9082/
// 

//main.cpp
		#include "Point.h"
		#include <iostream>
		#include "Array.cpp"
		#include <exception>
		using namespace std;

/*template<class Type>
int Array<int>::m_size_default = 10;

template<class Type>
int Array<double>::m_size_default = 10;*/

int main()
{


	Array<int> intArray1;
    Array<int> intArray2;
    Array<double> doubleArray;
 
    cout<<intArray1.DefaultSize()<<endl;
    cout<<intArray2.DefaultSize()<<endl;
    cout<<doubleArray.DefaultSize()<<endl; // line  
 
    intArray1.DefaultSize(15);
   
    cout<<intArray1.DefaultSize()<<endl;
    cout<<intArray2.DefaultSize()<<endl;
    cout<<doubleArray.DefaultSize()<<endl;
	
}




1>------ Build started: Project: 4.2b - Ex 1. Static Variable for Array Def Size. Templates, Configuration: Release Win32 ------
1> main.cpp
1>c:\all my\с++\ha level 6\solution level 6\solution level 6\4.2b - ex1. static variable for array def size. templates\Array.cpp(10): error C3211: 'Array<Type>::m_size_default' : explicit specialization is using partial specialization syntax, use template <> instead
1> with
1> [
1> Type=int
1> ]
1> c:\all my\с++\ha level 6\solution level 6\solution level 6\4.2b - ex1. static variable for array def size. templates\Array.h(20) : see declaration of 'Array<Type>::m_size_default'
1> with
1> [
1> Type=int
1> ]
1>c:\all my\с++\ha level 6\solution level 6\solution level 6\4.2b - ex1. static variable for array def size. templates\Array.cpp(13): error C3211: 'Array<Type>::m_size_default' : explicit specialization is using partial specialization syntax, use template <> instead
1> with
1> [
1> Type=double
1> ]
1> c:\all my\с++\ha level 6\solution level 6\solution level 6\4.2b - ex1. static variable for array def size. templates\Array.h(20) : see declaration of 'Array<Type>::m_size_default'
1> with
1> [
1> Type=double
1> ]
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Was This Post Helpful? 0
  • +
  • -

#8 vividexstance  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 660
  • View blog
  • Posts: 2,270
  • Joined: 31-December 10

Re: static variable and function with <template>

Posted 19 July 2012 - 08:55 AM

You need to place all the class template definitions inside the array.h file and get rid of the .cpp file, unless there's something that isn't template related inside it.
Was This Post Helpful? 1
  • +
  • -

#9 leeto  Icon User is offline

  • New D.I.C Head

Reputation: -3
  • View blog
  • Posts: 38
  • Joined: 17-June 12

Re: static variable and function with <template>

Posted 19 July 2012 - 08:57 AM

View Postjimblumberg, on 19 July 2012 - 08:30 AM, said:

Did you implement the changes I suggested?

What are you actually trying to accomplish by trying to make your functions static?

Jim


No, again they don't need.

This's project compile very well try it.

//array.h
#ifndef Array_H
#define Array_H

template <class Type> //Remove the "=double" default parameter.
class Array
{
private:
  int m_size;
  Type* m_data; //m_data should be a pointer, since you want to allocate data to it

public:
  Array();
  Array(int new_size);
  Array(const Array<Type>& ar);
  ~Array(); //Don't make your destructor virtual. There is no reason to do it.
  const Type& Array<Type>::GetElement(int index) const;
  void Array<Type>::SetElement(const Type& type_object, int index);
  Array<Type>& operator=(const Array& ar); //Const correctness here.
  Type& Array<Type>::operator [] (int index);
  void Swap(Array& ar);  
};

//Implementation goes here

#endif

//point.h

#include "array.h"
#include <sstream>
#include <iostream>
using namespace std;


class Point
{
private:
    double m_x;                                
    double m_y;                                
public:
    // Constructors
    Point(): m_x(0), m_y(0) {};                            
	Point(double new_x, double new_y) : m_x(new_x), m_y(new_y) {};
	friend ostream& operator << (ostream& os, const Point& point)
{
    return os << point.ToString();
}
	std::string Point::ToString(void) const                // create a string representation of a point
{
// create a string like: “Point(1.5, 3.9)”
      std::ostringstream os;
    os << m_x << " , " << m_y;
    std::string double_string = os.str();
 
    return "Point(" + double_string + ")";
}
};

//array.cpp
#include "Array.h"
#include <sstream>
#include <iostream>
#include <exception>
using namespace std;
#ifndef Array_CPP
#define Array_CPP


template <class Type>
Array<Type>::Array() : m_size(10), m_data(0)
{ 

}

template <class Type>
Array<Type>::Array(int new_size) : m_size(new_size), m_data(new Type[new_size])
{ 

}

template <class Type>
Array<Type>::~Array()
{
  //Technically, the if is not necessary
  if(m_data)
  {
    delete[] m_data;
    m_data = 0;
  }

  //Not necessary either, but just to be clean
  m_size = 0;
}

template <class Type>
Array<Type>::Array(const Array& ar) : m_data(0), m_size(0)
{
  if(!ar.m_data) {return;}

  Array tmp; //Copy construct into another temporary array, this way, if something throws, tmp will clean itself up.

  //Create the array
  tmp.m_data = new Type[ar.m_size];
  tmp.m_size = ar.m_size;

  //Copy the array elements
  for(int i = 0; i < tmp.m_size; ++i)
    {tmp.m_data[i] = ar.m_data[i];}

  //All done! swap into this!
  this->Swap(tmp);
}

template <class Type>
Array<Type>& Array<Type>::operator=(const Array& ar)
{
  //Check self assign:
  if(this == &ar) {return *this;}

  Array<Type> copy(ar); //Create a copy of ar; If this fails, then *this will not be changed, and nothing will leak

  //Succeeded creating copy. Now we can put it inside this
  this->Swap(copy); //And then swap the copy into this!

  return *this;
}

template <class Type>
void Array<Type>::Swap(Array& ar)
{
  Type* data = m_data;
  int   size = m_size;
  m_data = ar.m_data;
  m_size = ar.m_size;
  ar.m_data = data;
  ar.m_size = size;
}

template <class Type> 
void Array<Type>::SetElement(const Type& type_object, int index)
{

		if (index >= m_size || index < 0 )
		{ throw std:: out_of_range ("out of range error in void Array<Type>::SetElement");}
		m_data[index] = type_object;
		cout << "Set Element " << type_object  << endl;

	
}
template <class Type> 
const Type& Array<Type>::GetElement(int index) const
{
	
		if (index >= m_size || index < 0)
		{ throw std::out_of_range ("Out of range error in void Array<Type>::GetElement");} 

	return m_data[index];
}
template <class Type> 
Type& Array<Type>::operator [] (int index) 
{
    cout << "Array [] operator" << endl;
 
    if (index >= this->m_size)
	{
        cout << "i am hreeeee" << endl;
        return this->m_data[0];
	}
    return m_data[index];
}

#endif //Array_CPP

// NOte: 1. там надо было по заданию вообщем в самом конце надо какой синтекст внедрить в мейн и посмтореть что получается 
// не забыть это доделать. 2. еще надо вывести клвсс поинт реализацию в отдельный спп 
/*
In a previous exercise we created an Array class that stores Point objects. The disadvantage of this class was that it only stores Point objects. If we want to have an array class for Lines, we need to copy the code and replace references to Point to Line. This is a lot of work and makes maintenance more difficult. A bug in one version has to be fixed in the other versions as well. Better is to use the same code for different data types. This is possible using templates as shown in Figure 8.


Figure 8: Templated Array class containing Ts

Thus transform the Array class for points created earlier into a template class:
In the header file, declare the Array class as a template of type T.
Replace all references to Point with T.
Where an array is used as input or output, replace Array by Array<T>.
In the source file, every function must be declared as a template of type T.
The functions are now not a member of Array anymore but a member of Array<T>.
Further replace all references to Point with T.
Finally where an array is used as input or output, replace Array by Array<T>.
Don’t forget that the test program should now include the source file instead of the header file. Therefore, the source file should now also include #ifndef/#define/#endif statements.
In the test program create an array of points and test it:
Code (cpp):
Array<Point> points(size);
Tip, by placing the following code at the end of the array header file, but before the header file’s #endif, the client can keep including the header file for template classes instead of the source file. Can you explain how this works?:
Code (cpp):
#ifndef Array_cpp // Must be the same name as in source file #define
#include "Array.cpp"
#endif
*/ 
//
//
// QuantNet C++ course
// LEVEL 6. 4.2a - Introduction to Templates
// https://www.quantnet.com/threads/level-6-homework.7857/
// Exercise 1: Templated Array Class
//
// Created by Denis Igoshev
//
//main.cpp
		#include "point.h"
		#include <iostream>
		#include "array.cpp"
		#include <exception>
		using namespace std;

int main()
{
		try
		{
			Point *p1 = new Point (1,12);
			Point *p2 = new Point (13,112);
			Point *p3 = new Point (13,125);
				cout << endl;
			Array<Point> arr1(5);
			arr1.SetElement(*p1,4);
				cout << endl;

		cout <<"Get Element  " << arr1.GetElement(4)<<endl;
		cout <<	arr1.GetElement(3)<<endl;
			delete p1;

			cout << "now let's test [] overload operator" << endl;

	Array<Point>* my_Array3 = new Array<Point>(3);
	my_Array3->SetElement(*p2,0);
	my_Array3->SetElement(*p3,1);
 
	cout << "my_Array3 [] operator " << (*my_Array3)[1] << endl;

			return 0;
			delete my_Array3;


		}
		catch(const std::exception& e)
		{
			std::cout << e.what() << std::endl;
			throw;
		}
	
}



condition of problem with static function :

/*
Exercise 1: Static Variable for Array Default Size (optional)

Static variables, which are shared between all instances of a class,
behave slightly different with templates. We are going to test this with a static variable in
the Array class that indicates the default array size when using the default constructor.
Add a static data member to the Array class indicating the default size.
Initialise this static in the source file to a value.
Also add static functions to set and get the default size.
In the default constructor, use the static default size variable
instead of a literal value to set the array size.
Test the following code in the main program:
Code (cpp):
Array<int> intArray1;
Array<int> intArray2;
Array<double> doubleArray;

cout<<intArray1.DefaultSize()<<endl;
cout<<intArray2.DefaultSize()<<endl;
cout<<doubleArray.DefaultSize()<<endl;

intArray1.DefaultSize(15);

cout<<intArray1.DefaultSize()<<endl;
cout<<intArray2.DefaultSize()<<endl;
cout<<doubleArray.DefaultSize()<<endl;
What values are printed? Can you explain the result?
*/

View Postvividexstance, on 19 July 2012 - 08:55 AM, said:

You need to place all the class template definitions inside the array.h file and get rid of the .cpp file, unless there's something that isn't template related inside it.


I used project that compile well. Again I don't think that something relate with what you said
Was This Post Helpful? -2
  • +
  • -

#10 vividexstance  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 660
  • View blog
  • Posts: 2,270
  • Joined: 31-December 10

Re: static variable and function with <template>

Posted 19 July 2012 - 09:00 AM

Just a tip, now that everything is inside the Array header file, you really should remove the using directive (using namespace std;) because it can cause problems for anyone who uses the header file. The rule is not to have using directives or using declarations (using std::cout) in any of your header files. If you do remove it, remember to go through the code and add a std:: to any code that uses the standard C++ library (anything that is inside the std namespace).

This post has been edited by vividexstance: 19 July 2012 - 09:01 AM

Was This Post Helpful? 0
  • +
  • -

#11 jimblumberg  Icon User is offline

  • member icon


Reputation: 4071
  • View blog
  • Posts: 12,557
  • Joined: 25-December 09

Re: static variable and function with <template>

Posted 19 July 2012 - 10:12 AM

Quote

I used project that compile well.

If the project compiled properly then what is your problem?

From your last post:

Quote

No, again they don't need.

This's project compile very well try it.


I tried compiling your code and it will not compile for me for the reasons mentioned in post #3.

Jim
Was This Post Helpful? 0
  • +
  • -

#12 #define  Icon User is offline

  • Duke of Err
  • member icon

Reputation: 1344
  • View blog
  • Posts: 4,613
  • Joined: 19-February 09

Re: static variable and function with <template>

Posted 19 July 2012 - 06:43 PM

I don't think you need to try and specialize here.

template<class Type> // line 10 
int Array<int>::m_size_default = 10; // line 11

template<class Type> // line 13
int Array<double>::m_size_default = 10;




Just use the template as usual.

template<class Type>
int Array<Type>::m_size_default = 10;


Was This Post Helpful? 0
  • +
  • -

Page 1 of 1