Template error

Hey guys I am getting an error I don't understand when I compile this code. This what I get in my error window. Any suggestions? Thanks in advance.

1>------ Build started: Project: Assign 20, Configuration: Debug Win32 ------
1> Assgn20-1.cpp
1>c:\users\j-bird\documents\visual studio 2010\projects\assign 20\assign 20\assgn20-1.cpp(25): error C2664: 'std::basic_string<_Elem,_Traits,_Ax>::basic_string(const std::basic_string<_Elem,_Traits,_Ax> &)' : cannot convert parameter 1 from 'const int' to 'const std::basic_string<_Elem,_Traits,_Ax> &'
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>,
1> _Ax=std::allocator<char>
1> ]
1> Reason: cannot convert from 'const int' to 'const std::basic_string<_Elem,_Traits,_Ax>'
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>,
1> _Ax=std::allocator<char>
1> ]
1> No constructor could take the source type, or constructor overload resolution was ambiguous
1> c:\users\j-bird\documents\visual studio 2010\projects\assign 20\assign 20\assgn20-1.cpp(25) : while compiling class template member function 'std::string Array<T>::IndexOutOfBounds::getSubscript(void) const'
1> with
1> [
1> T=std::string
1> ]
1> c:\users\j-bird\documents\visual studio 2010\projects\assign 20\assign 20\assgn20-1.cpp(50) : see reference to class template instantiation 'Array<T>::IndexOutOfBounds' being compiled
1> with
1> [
1> T=std::string
1> ]
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

This is my 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
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
 #include <iostream>
#include <string>
using namespace std;

template <class T>
class Array
{
private:
    T * aptr;                     // pointer to array
    int arySize;					// size of array 
public:
    class IndexOutOfBounds			// exception class
    { 
    private:
        int subscript;				// bad subscript    
    public:
        IndexOutOfBounds(int s) : subscript(s)
        { }
        T getSubscript() const    	// accessor
        { return subscript; }
    };
    Array(int);                  // ctor
    Array(const Array & ary);    // copy ctor
    // overloaded assignment operator needed
    ~Array();                    // dtor
    int size() const             // returns array size
    { return arySize; }    
    // parameter is a subscrip; operator[]() returns a reference 
    // to element indexed by the subscript
    T & operator[](int sub);  // overloaded [] operator
};

int main()
{
    string boo = "boo";
    string hoo = "hoo";
    Array<string> str(3);	// Array object ary can hold three string elements
	  try {  	// store strings in Array and attempt to store at invalid index
       str[0] = boo;
		for (int num = 1; num <= 3; num++) {
			cout << "Storing \"boo\" + hoo at index " << num << endl;
			str[num] = str[num-1] + hoo;
		} // endfor
	  } // endtry
	  catch(Array<string>::IndexOutOfBounds e)
	  {
		   cout << " ** Index " << e.getSubscript() << " is invalid\n\n";
	  } // endcatch*/
    
	  Array<int> ary(10);		// Array object ary can hold ten elements
	  try {     // store values in Array and attempt to store at invalid index
		   for (int num = 0; num <= 10; num++) {
          ary[num] = 1 + num;
			cout << "Stored " << ary[num] << " at index " << num << endl;
		   } // endfor
	  } // endtry
	  catch(Array<int>::IndexOutOfBounds e)
	  {
		   cout << " ** Index " << e.getSubscript() << " is invalid\n\n";
	  } // endcatch
    
    Array<double> aryD(8);	// Array object ary can hold eight elements
	  try {
        // store values in Array and attempt to store at invalid index
		   for (int num = 0; num <= 8; num++) {
          aryD[num] = 1.1 + num;
			cout << "Stored " << aryD[num] << " at index " << num << endl;
		   } // endfor
	  } // endtry
	  catch(Array<double>::IndexOutOfBounds e)
	  {
		   cout << " ** Index " << e.getSubscript() << " is invalid\n\n";
	  } // endcatch
    
	  return 0;
}
   
// function implementation for the Array class

template <class T>
Array<T>::Array(int s) : arySize(s)        // ctor
{
    aptr = new int[s];     // allocate space for elements
    for (int k = 0; k < arySize; k++)
        *(aptr + k) = 0;    // initialize elements to 0
}

template <class T>
Array<T>::Array(const Array & obj)    // copy ctor
{
    arySize = obj.arySize;      // set arySize
    aptr = new T[arySize];    // allocate space to copy Array
    for(int k = 0; k < arySize; k++)    // copy Array
        *(aptr + k) = *(obj.aptr + k);
}

template <class T>
Array<T>::~Array()
{
    if (arySize > 0)
        delete [] aptr;         // free dynamic memory
}

template <class T>
T & Array<T>::operator[](int sub) 
{
    if (sub < 0 || sub >= arySize)
        throw IndexOutOfBounds(sub);
    return aptr[sub];
}
Try either changing line 15 to T subscript; and change line 17 to reflect that, or change line 19 to int getSubscript() const. Probably the latter.
Last edited on
I tried both neither one worked though. Thanks for the suggestion though. Any other suggestions?
NT was right, that is "one" of your problems.
Working on the errors VS shows me.

1
2
T getSubscript() const    	// accessor
      { return subscript; } 
Subscript is always an int, no need to try and return T from this function.


aptr = new int[s]; // allocate space for elements
Aptr can be any variable type (in this case a string). You can't use new int here. Use new T[s];


1
2
for (int k = 0; k < arySize; k++)
      *(aptr + k) = 0;    // initialize elements to 0 

This is a harder one...From what I can see it will complain "operator = is ambiguous" because it can't see if it is working on a string or a char*. Changing it to *(char*)(aptr + k) = 0; seems to fix the error but other people could tell you better than me.
1
2
3
4
5
6
7
template <class T>
Array<T>::Array(int s) : arySize(s)        // ctor
{
    aptr = new int[s];     // allocate space for elements
    for (int k = 0; k < arySize; k++)
        *(aptr + k) = 0;    // initialize elements to 0
}


James2250 wrote:
This is a harder one...From what I can see it will complain "operator = is ambiguous" because it can't see if it is working on a string or a char*. Changing it to *(char*)(aptr + k) = 0; seems to fix the error but other people could tell you better than me.


The problem is not because the function does not know if a std::string or a char* is being worked on. In fact, prior to instantiation, std::string and char* have no meaning with respect to T. The caveat with writing template definitions is that there is no implicit conversion. Everything must be explicit.

1
2
3
4
5
6
7
8
9
template <class T>
Array<T>::Array(int s) : arySize(s)        // ctor
{
    aptr = new T[s];     // Do not assume the type to be int
    for (int k = 0; k < arySize; k++)
        *(aptr + k) = T();    // Default construct an object of type T
                      //Avoid using an explicit value if you can (even 0). This is because
                      //    you don't know if type T can be constructed from such a value.
}


*(char*)(aptr + k) = 0;
Casting like this is dangerous, especially considering the main function uses instantiations with std::string and double. For future reference:
static_cast<yourType>(variable) will help the compiler spit out errors when you are attempting to make incorrect casts (such as attempting to cast std::string* to char*).
Last edited on
OK I see the logic behind that. I changed it and its trying to run, but now it's crashing saying I have an Invalid NULL pointer. It works if I comment out the first try catch in main(). My teacher even had this problem with his demo today in class. Thanks for the tips guys!
Last edited on
Try changing your for loop to num < 3 rather than num <= 3, otherwise you will go out of bounds.
Topic archived. No new replies allowed.