Non type parameters on class templates

3rd problem with template.. sigh

Page 1 of 1

13 Replies - 1129 Views - Last Post: 27 November 2009 - 10:48 PM Rate Topic: -----

#1 xenoslash  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 89
  • Joined: 19-August 09

Non type parameters on class templates

Posted 26 November 2009 - 01:53 AM

Unresolved external error.. AGAIN!! ARGH!! (swearing) <- me

Anyways, this time it's about non type parameter

long code, so I'll just simplify the problem

template <typename T, int s=0>
class Array
{
public:
	Array( T*);
		
		//blablabla

private:
	int size;
	T* arr;

}


I'm trying to separate the implementation from the header file , but how do I do this for the constructor?

this is what I did, but it obviously won't work
template<typename T>
Array<T>::Array( T* a)
	:size((s>=0 ? s : 0)),   //here is the problem
	arr(a)
	{
	}



How do I use the 's' from the header file template??
something like template class Array::s ??

Is This A Good Question/Topic? 0
  • +

Replies To: Non type parameters on class templates

#2 EdwinNameless  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 120
  • View blog
  • Posts: 710
  • Joined: 15-October 09

Re: Non type parameters on class templates

Posted 26 November 2009 - 02:19 AM

I don't understand why you want to use a template for this. How about:

template <typename T>
class Array
{
public:
  Array(T*, int s = 0);
  
  //blablabla

private:
  int size;
  T* arr; 
};



and then, the implementation:

template<typename T>
Array<T>::Array(T* a, int s)
  :size((s>=0 ? s : 0)), 
   arr(a)
{
}




?
Was This Post Helpful? 0
  • +
  • -

#3 EdwinNameless  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 120
  • View blog
  • Posts: 710
  • Joined: 15-October 09

Re: Non type parameters on class templates

Posted 26 November 2009 - 03:02 AM

Ok, I do realise I didn't give a proper answer, even though I still think I would probably use a constructor for this...


template <typename T, int n=0>
class Array
{
public:
  Array(); // I've added this one for convenience.
  Array(T*);
  
  //blablabla
private:
  int size;
  T* arr; 
};





and then, the implementation:

template<typename T, int n>
Array<T,n>::Array(T* a)
  :size((n>=0 ? n : 0)),   
   arr(a)
{
}

template<typename T, int n>
Array<T,n>::Array()
  :size((n>=0 ? n : 0))
{
}


int main() {
  Array<int> a;
  return 0;
}




?
[/quote]
Was This Post Helpful? 0
  • +
  • -

#4 Bench  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 855
  • View blog
  • Posts: 2,338
  • Joined: 20-August 07

Re: Non type parameters on class templates

Posted 26 November 2009 - 03:58 AM

if the size of the array is going to be a template parameter (A compile time constant) then the size can't change, so you may as well use a statically allocated array.
template <typename T, int size>
class Array
{
    T arr[size];
}; 
If the size of the array needs to change at runtime (i.e. it needs to be dynamically resized), then passing its size as a template parameter isn't really such a good idea.
Was This Post Helpful? 0
  • +
  • -

#5 xenoslash  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 89
  • Joined: 19-August 09

Re: Non type parameters on class templates

Posted 26 November 2009 - 07:55 AM

@Edwin
Unresolved external -bleep- error ...
Never thought that template will be this hard!!! ARGH!!

I have even included these lines

template class Array <int>;
template class Array <char>;
template class Array <double>;

@Bench

I have even made a new file and simplified the code
still that -bleep- error!!!
Can anyone please post a really2 comprehensive link on this topic??
The other link I got was helpful, but didn't mention anything bout non type parameter, and how I should implement them in a separate cpp file.

Here is the really simplified code by the way

header
#ifndef ARRAY_H
#define ARRAY_H

template <typename T, int s=0>
class Array
{
public:
	Array( T*);
private:
	T arr[s];
};
#endif



implementation

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


template<typename T, int s>
Array<T,s>::Array( T* a)
	:arr(a)
	{
	}


template class Array<char>;
template class Array<int>;	//tell the compiler to instatiate these versions
template class Array<double>;





test file

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

int main()
{


const int ACOUNT = 5; // size of array a
const int BCOUNT = 7; // size of array b
const int CCOUNT = 6; // size of array c

int a[ ACOUNT ] = { 1, 2, 3, 4, 5 };
double b[ BCOUNT ] = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7 };
char c[ CCOUNT ] = "HELLO"; // 6th position for null

Array<int, ACOUNT> ar1(a);
Array<double,BCOUNT> ar2(b);
Array<char, CCOUNT> ar3(c);
return 0;
}



Sigh... does everyone else have lotsa problems with template like I do?

@Edwin
Unresolved external -bleep- error ...
Never thought that template will be this hard!!! ARGH!!

I have even included these lines

template class Array <int>;
template class Array <char>;
template class Array <double>;

@Bench

I have even made a new file and simplified the code
still that -bleep- error!!!
Can anyone please post a really2 comprehensive link on this topic??
The other link I got was helpful, but didn't mention anything bout non type parameter, and how I should implement them in a separate cpp file.

Here is the really simplified code by the way

header
#ifndef ARRAY_H
#define ARRAY_H

template <typename T, int s=0>
class Array
{
public:
	Array( T*);
private:
	T arr[s];
};
#endif



implementation

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


template<typename T, int s>
Array<T,s>::Array( T* a)
	:arr(a)
	{
	}


template class Array<char>;
template class Array<int>;	//tell the compiler to instatiate these versions
template class Array<double>;





test file

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

int main()
{


const int ACOUNT = 5; // size of array a
const int BCOUNT = 7; // size of array b
const int CCOUNT = 6; // size of array c

int a[ ACOUNT ] = { 1, 2, 3, 4, 5 };
double b[ BCOUNT ] = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7 };
char c[ CCOUNT ] = "HELLO"; // 6th position for null

Array<int, ACOUNT> ar1(a);
Array<double,BCOUNT> ar2(b);
Array<char, CCOUNT> ar3(c);
return 0;
}



Sigh... does everyone else have lotsa problems with template like I do?
Was This Post Helpful? 0
  • +
  • -

#6 KYA  Icon User is offline

  • g++ jameson.cpp -o beverage
  • member icon

Reputation: 3093
  • View blog
  • Posts: 19,139
  • Joined: 14-September 07

Re: Non type parameters on class templates

Posted 26 November 2009 - 08:05 AM

You're using two template params:

template class Array<char, int>;
template class Array<int, int>;  
template class Array<double, int>;




Not sure if it that will solve all of your problems, I didn't compile/run your code.


This compiles. I did some changes:

template <typename T, int s=0>
class Array
{
public:
	Array();
	~Array();
private:
	T* arr;
};


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


template<typename T, int s>
Array<T,s>::Array()
{
	arr = new T[s];
}

template<typename T, int s>
Array<T,s>::~Array(){
	delete[] arr;
}


const int ACOUNT = 5; // size of array a
const int BCOUNT = 7; // size of array b
const int CCOUNT = 6; // size of array c

template class Array<char, CCOUNT>;
template class Array<int, ACOUNT>;  
template class Array<double, BCOUNT>;


int main(){
	Array<int, ACOUNT>* thing = new Array<int, ACOUNT>();
	delete thing;
	return 0;
}






All in all this seems pointless. If you know at compile time, the size of your array, why jump through all these hoops? (Bench already mentioned it, I just felt like saying it again).

This post has been edited by KYA: 26 November 2009 - 08:22 AM

Was This Post Helpful? 0
  • +
  • -

#7 xenoslash  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 89
  • Joined: 19-August 09

Re: Non type parameters on class templates

Posted 26 November 2009 - 08:14 AM

Tried that and 5 more errors appeared
I think it's because
<int, int>
the second int is wrong because class template is <typename T, int s>

Oh, and just being curious here, but isn't this

template class Array<char>;

the same as

template class Array<char, 0>; //0 is set as the default value for s

and hence fulfill the parameters of the template , which are

<typename T, int s>

or do I need to put the 0 manually like this

template class Array<char, 0>;

Here are the errors by the way..


test.obj : error LNK2019: unresolved external symbol "public: __thiscall Array<char,6>::Array<char,6>(char *)" (??0?$Array@D$05@@QAE@PAD@Z) referenced in function _main
test.obj : error LNK2019: unresolved external symbol "public: __thiscall Array<double,7>::Array<double,7>(double *)" (??0?$Array@N$06@@QAE@PAN@Z) referenced in function _main
test.obj : error LNK2019: unresolved external symbol "public: __thiscall Array<int,5>::Array<int,5>(int *)" (??0?$Array@H$04@@QAE@PAH@Z) referenced in function _main
C:\Documents and Settings\joe\My Documents\Visual Studio 2008\Projects\Array\Debug\Array.exe : fatal error LNK1120: 3 unresolved externals

BZZT! UNRESOLVED EXTERNALS!!!

I will just go to sleep now -.-
Was This Post Helpful? 0
  • +
  • -

#8 KYA  Icon User is offline

  • g++ jameson.cpp -o beverage
  • member icon

Reputation: 3093
  • View blog
  • Posts: 19,139
  • Joined: 14-September 07

Re: Non type parameters on class templates

Posted 26 November 2009 - 08:23 AM

I edited my post, take a look now.
Was This Post Helpful? 0
  • +
  • -

#9 Bench  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 855
  • View blog
  • Posts: 2,338
  • Joined: 20-August 07

Re: Non type parameters on class templates

Posted 26 November 2009 - 09:00 AM

I've just realised what you meant by "separating header and implementation"; it might come as a bit of a surprise (or not) that you can't do this with template classes in quite the same way as with non-template classes.

If i'm not mistaken, your original error was a linker error because you had your Array constructor body in a CPP file, but your template class declaration in a header. Unfortunately template classes must be put into header files in their entirety. - Actually there is a preprocessor 'trick' you can do with #include on the .CPP file to circumvent this problem, but the basic principle is that anywhere you use your Array template class, you need to directly include all of its member definitions aswell, and not just the class declaration in your header.
look here: http://www.parashift....html#faq-35.12

If you're going to be playing more with templates, you should probably keep that entire FAQ as one of your bookmarks - theres an amazing amount of good information there about the peculiarities of templates (and the language as a whole).


as for the other problem of creating an instance of Array<typename T,int s> - think about what the parameters between < and > mean.
  • typename T Pretty obvious, give it a type, and 'T' means "any type"
  • int s I think you were trying to pass 'int' here, but 's' is not a typename, its an int, meaning that you need to pass it a number. so to create a "concrete" Array, your declaration should look like Array<int, 5> my_array; - then you'll end up with T arr[s] turning into int arr[5]. (obviously arr[0] won't compile, you'll get an error complaining about a zero-sized array)
.

I don't know of many good free online resources which cover templates in depth (Most of the information seems to be a little scattered). How far does your book go? Bruce Eckel's free e-book "Thinking in C++" has chapters in templates (Volume 1 gives you an introduction, then another chapter in volume 2 goes into more depth)
http://www.mindview....ingInCPP2e.html
**Note - his site seems to be down at the time of writing this, although its still regularly maintained, so i'm sure it'll be back up soon, if not, there are loads of places to download it if you look on google**

This post has been edited by Bench: 26 November 2009 - 09:08 AM

Was This Post Helpful? 0
  • +
  • -

#10 xenoslash  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 89
  • Joined: 19-August 09

Re: Non type parameters on class templates

Posted 26 November 2009 - 10:26 PM

@Bench
I'm using Deitel's c++ how to program 5th edition
The template section is very2 short and does not mention anything about these errors I keep getting

@KYA
I already tried that and it worked. I apologize for not making it clear that I am trying to separate the implementation cpp from the header file. (My book said this is good software engineering and bla3).

Fine2 I will just combine the header file and implementation cpp into one.
Good software engineering ==== headaches

Oh yeah, I don't think this question has been answered yet

How do I access the variable s from the template
template <typename T, int s>

Can I gain access to s from another file???
Let's, say with member function
getS()
{
return s;
}

or something like that?
Was This Post Helpful? 0
  • +
  • -

#11 Bench  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 855
  • View blog
  • Posts: 2,338
  • Joined: 20-August 07

Re: Non type parameters on class templates

Posted 27 November 2009 - 02:32 AM

Quote

I already tried that and it worked. I apologize for not making it clear that I am trying to separate the implementation cpp from the header file. (My book said this is good software engineering and bla3)
Yes, its usually good practise, but templates are a special case, and unfortunately you can't split your class definitions into CPP files so easily as; at least for now, I believe the next C++ Standard (C++0x) is going to change something to allow you to separate them (if/when that becomes widely supported by all the mainstream compilers I expect the issue will fade away)



Quote

How do I access the variable s from the template
template <typename T, int s>

Can I gain access to s from another file???
Let's, say with member function
getS()
{
return s;
}

or something like that?
Yes that will work, but its a little unnecessary since s is a compile time constant value (Remember that templates are macros; they generate code before the compiler starts) - the most common thing to do with template int/bool arguments is to turn them into enums, since doing this shows their 'constant value' status to the outside world.
template<int N>
class x
{
public:
    enum { num = N };
};

#include <iostream>
int main()
{
    x<5> foo;
    std::cout << foo.num << std::endl;
    std::cout << x<10>::num << std::endl;
} 

Was This Post Helpful? 1
  • +
  • -

#12 xenoslash  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 89
  • Joined: 19-August 09

Re: Non type parameters on class templates

Posted 27 November 2009 - 04:11 AM

enum { num = N };
I see! Thanks for above line
New question

Overload function template printArray() with a nontemplate version that specifically prints an array of character strings in neat, tabular, column format.

this is what I did

void Array<char>::printArray()
{
for(int i=0; i<s; i++)
{
cout<<arr[i]<<' ';
}
cout<<endl;
}

but this will only work when s==0

so I tried filling the integer parameter with this

template <int s>
void Array<char, s> bla3

but the error I got here is
function template has already been defined
and template argument list following class template name must list parameters in the order used in template parameter list

and also, what does the question mean by neat, tabular, column format? :P
Was This Post Helpful? 0
  • +
  • -

#13 Bench  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 855
  • View blog
  • Posts: 2,338
  • Joined: 20-August 07

Re: Non type parameters on class templates

Posted 27 November 2009 - 05:41 AM

What you're trying to do is usually known as partial template specialisation

At first, the final answer from Victor Bazarov in this thread seemed to suggest that its not possible to do this cleanly. http://www.velocityr...r-function.html

Quote

to specialise a member of a template class you need to first specialise the class itself. It's a limitation of the language.



So when I tried it, I thought this was probably the best solution you were going to get, and you'd just be stuck with doing a copy/paste job on your template class:
template<typename T, int N>
class x
{
public:
    enum { num = N };
    void foo();
};

template<int N>
class x<char, N>
{
public:
    enum { num = N };
    void foo(); 
}; 

#include <iostream>
template<typename T, int N>
void x<T,N>::foo()
{ 
    std::cout << "typename = T" << std::endl; 
}

template<int N>
void x<char, N>::foo()
{ 
    std::cout << "Typename = char" << std::endl; 
}


But then a thought crossed my mind as to why the language doesn't let you do this - simply because it doesn't need to.
it's equally possible to move out the rest of the class which doesn't need specialisation to a base class; leaving your actual Array class only defining the function you want to specialise (The base class isn't going to be used polymorphically so no need for any fancy 'virtual' stuff, and no need to define the printArray() in the base class either)
template<typename T, int N>
class base // All of the non-specialised stuff goes in here
{
public:
    enum { num = N };

    //Make sure that the derived classes are friends
    template <typename,int> class x;
    friend class x<T,N>;
};

template<typename T, int N>
class x : public base<T,N>
{
public:
    void foo();
};

// This class is used to specialise for char
template<int N>
class x<char, N> : public base<char,N>
{
public:
    void foo(); 
};


#include <iostream>
template<typename T, int N>
void x<T,N>::foo()
{ 
    std::cout << "typename = T" << std::endl; 
}

template<int N>
void x<char, N>::foo()
{ 
    std::cout << "Typename = char" << std::endl; 
} 


View Postxenoslash, on 27 Nov, 2009 - 11:11 AM, said:

and also, what does the question mean by neat, tabular, column format? :P
If I were to take a wild stab in the dark, I'd guess that the question wants you to use some stream manipulators from <iomanip> to align your output vertically
http://www.cprogramm...al/iomanip.html

This post has been edited by Bench: 27 November 2009 - 06:09 AM

Was This Post Helpful? 0
  • +
  • -

#14 xenoslash  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 89
  • Joined: 19-August 09

Re: Non type parameters on class templates

Posted 27 November 2009 - 10:48 PM

@Bench
J00 . IZ . A . JEAN-EAOUS!!
You don't know how happy I am to get this code to compile :P
Thanks a lot!!
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1