Template Class Specialization help

I've been trying to do this for the last 3 days and haven't made any progress. I'm making an array class into a template, and got that to work fine, but I need to change the constructor if the type is a string. No matter what I try, I can't get full or partial specialization to work. The class works fine if I take out the attempt at specialization.

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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#include <iostream>
#include <iomanip>
#include <cstdlib>
using namespace std;

template < typename T >
class Array
{
	friend ostream &operator<< <T>( ostream &, const Array<T> & ); // <T>?
	friend istream &operator>> <T>( istream &, Array<T> & );

private:
	int size;
	T* ptr;

public:
	Array( int arraySize = 10 );
	Array( const Array<T> & );
	~Array();
	int getSize() const;

	const Array &operator=( const Array<T> & );
	bool operator==( const Array<T> & ) const;

	bool operator!=( const Array<T> &right ) const
	{
		return ! ( *this == right );
	}

	T &operator[]( int );
	T operator[]( int ) const;
};

template < typename T >
inline Array<T>::Array( int arraySize )
{
	size = ( arraySize > 0 ? arraySize : 10 );
	ptr = new T[ size ];

	for ( int i = 0; i < size; i++ )
		ptr[ i ] = 0;
}

inline Array<string>::Array( int arraySize ) // doesn't work!
{
	size = ( arraySize > 0 ? arraySize : 10 );
	ptr = new string[ size ];

	for ( int i = 0; i < size; i++ )
		ptr[ i ] = "0";
}

template < typename T >
inline Array<T>::Array ( const Array<T> &arrayToCopy )
	: size( arrayToCopy.size )
{
	ptr = new T[ size ];

	for ( int i = 0; i < size; i++ )
		ptr[ i ] = arrayToCopy.ptr[ i ];
}

template < typename T >
inline Array<T>::~Array()
{
	delete [] ptr;
}

template < typename T >
inline int Array<T>::getSize() const
{
	return size;
}

template < typename T >
inline const Array<T>& Array<T>::operator=( const Array<T> &right )
{
	if ( &right != this )
	{
		if ( size != right.size )
		{
			delete [] ptr;
			size = right.size;
			ptr = new T[ size ];
		}

		for ( int i = 0; i < size; i++ )
			ptr[ i ] = right.ptr[ i ];
	}

	return *this;
}

template < typename T >
inline bool Array<T>::operator==( const Array<T> &right ) const
{
	if ( size != right.size )
		return false;

	for ( int i = 0; i < size; i++ )
		if ( ptr[ i ] != right.ptr[ i ] )
			return false;

	return true;
}

template < typename T >
inline T& Array<T>::operator[]( int subscript )
{
	if ( subscript < 0 || subscript >= size ) //exception
	{
		cerr << "\nError: Subscript " << subscript << " out of range" << endl;
		exit( 1 );
	}
	
	return ptr[ subscript ];
}

template < typename T >
inline T Array<T>::operator[]( int subscript ) const
{
	if ( subscript < 0 || subscript >= size )
	{
		cerr << " \nError: Subscript " << subscript << " out of range" << endl;
		exit( 1 );
	}

	return ptr[ subscript ];
}

template < typename T >
istream &operator>> ( istream &input, Array<T> &a )
{
	for ( int i = 0; i < a.size; i++ )
		input >> a.ptr[ i ];

	return input;
}

template < typename T >
ostream &operator<< ( ostream &output, const Array<T> &a )
{
	int i;

	for ( i = 0; i < a.size; i++ )
	{
		output << setw( 12 ) << a.ptr[ i ];

		if ( ( i + 1 ) % 4 == 0 )
			output << endl;
	}

	if ( i % 4 != 0 )
		output << endl;

	return output;
}


Main:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <string>
#include "Array.h"
using namespace std;

int main()
{
	Array< int > tester;
	Array< string > breaker;

	cout << "ints:\n" << tester;
	cout << "strings:\n" << breaker;

	cin.get();
	return 0;
}


I can't figure out how to do this at all. I'd really appreciate a point in the right direction. These are the errors i'm getting with this attempt:

1
2
3
4
5
1>main.obj : error LNK2019: unresolved external symbol "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl
 std::<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class Array<class
 std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > const &)" 
(?<<@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@ABV?$Array@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@@@Z) referenced in function _main
1>c:\users\name\documents\visual studio 2010\Projects\TemplateTester\Debug\TemplateTester.exe : fatal error LNK1120: 1 unresolved externals
Last edited on
Try :

1
2
3
4
5
6
7
8
template < typename T >
class Array
{
    template <typename T>
    friend ostream &operator<< ( ostream &, const Array<T> & ); 
    
    template <typename T>
    friend istream &operator>> ( istream &, const  Array<T> & ); //const added  




NOTE:
The above should work using microsoft (as you are) - BUT
Using <T> for the the operator << and >> overloads may cause a problem when compiling with
GCC/Mingw - you will get error about the clash of typename T with the typename T used for the
class Array.
In which case, you can change the template typenames for the operator << and >> functions
to U or some other letter.

1
2
template <typename U>
    friend ostream &operator<< ( ostream &, const Array<U> & ); 
Last edited on
I can't believe those 2 were ruining everything. Thank you so much.
Topic archived. No new replies allowed.