### Template issues

Hi all,

I was wondering if someone could help me with one of the exercises I have for uni,

The program itself works fine, however when I attempted to add a template to the class I keep getting the errors: "Cannot use template 'Bivec<T>' without specifying specialization perameters (Borland Compiler E2102) and "Declaration Terminated Incorrectly" referring to the Bivec class' constructor:

`Bivec::Bivec (int lo, int hi, T initial_value): v(hi - lo + 1), low(lo)`

Any suggestions most welcome,

Thanks,

Full program code:

 ``123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190`` ``````#include #include #include #include using namespace std; class Out_of_bounds { public: Out_of_bounds(int elem) : bval(elem) {} int badval() const {return bval;} private: int bval; }; class Pop_on_empty {}; template class Bivec { public: Bivec() {low = 0;} Bivec (int lo, int hi, T initial_value); void push_back(T); void push_front(T); T pop_back() throw (Pop_on_empty); T pop_front() throw (Pop_on_empty); int& operator[](int) throw (Out_of_bounds); void display() const; bool empty() const {return v.size() == 0; } Bivec(const Bivec& bx) { copy(bx); } ~Bivec() { free(); } const Bivec& operator=(const Bivec&); private: vector v; int low; void copy(const Bivec&); void free(); }; Bivec::Bivec (int lo, int hi, T initial_value): v(hi - lo + 1), low(lo) { for (int i = 0; i < static_cast(v.size()); i++) v[i] = new T(initial_value); } template template void Bivec::push_back(T x) { v.push_back(new T(x)); } template void Bivec::push_front(T x) { v.push_back(new T(NULL)); /*for (int i = 1; i < static_cast(v.size()); i++) v[i] = v[i - 1];*/ for (int i = v.size() - 1; i > 0; i--) v[i] = v[i-1]; v[0] = new T(x); low--; } template T Bivec::pop_back() throw (Pop_on_empty) { if (v.empty()) throw Pop_on_empty(); else { T g = *v[v.size() - 1]; v.pop_back(); return g; } } template T Bivec::pop_front() throw (Pop_on_empty) { if (v.empty()) throw Pop_on_empty(); else { T g = *v[0]; for (int i = 1; i < static_cast(v.size()); i++) v[i - 1] = v[i]; v.pop_back(); low++; return g; } } template int& Bivec::operator[](int n) throw (Out_of_bounds) { if (n < low || n >= low + static_cast(v.size())) throw Out_of_bounds(n); return *v[n - low]; } template void Bivec::display() const { for (int i = 0; i < static_cast(v.size()); i++) cout << *v[i] << " "; cout << endl; } template const Bivec& Bivec::operator=(const Bivec& old) { if (this != &old) { free(); copy(old); } return *this; } template void Bivec::copy(const Bivec& old) { v = old.v; low = old.low; for (int i = 0; i < static_cast(v.size()); i++) v[i] = new int(*old.v[i]); } template void Bivec::free() { while (v.size() > 0) { v.pop_back(); } } int main() {try{ Bivec b1; cout << "b1, initially empty: "; b1.display(); for (int i = 0; i < 10; i++) b1.push_back(i); cout << "b1, after push_backs: "; b1.display(); b1.push_front(66); b1.push_front(77); cout << "b1, after push_fronts: "; b1.display(); int last = b1.pop_back(), first = b1.pop_front(); cout << "last was " << last << ", first was " << first << endl; cout << "b1, after pops: "; b1.display(); cout << "b1[-1] " << b1[-1] << ", b1[0] " << b1[0] << ", b1[8] " << b1[8] << endl; b1[-1] = 88; cout << "b1, after b1[-1] = 88: "; b1.display(); Bivec b2(-5, +5, 0); cout << "b2, as constructed: "; b2.display(); Bivec b3(b1); cout << "b3, copy-constructed from b1: "; b3.display(); b3 = b2; cout << "b3, after b3 = b2: "; b3.display(); cout << "Program should now terminate with exception" << endl; // cout << b1[50]; // should throw exception while( true ) b3.pop_back(); // should throw exception } catch(const Out_of_bounds& ob) { cerr << "Invalid subscript " << ob.badval() << endl; exit(1); } catch(Pop_on_empty) { cerr << "Popping empty Bivec" << endl; exit(1); } } // matches { before try, needed for Borland ``````
Last edited on
Just look at the way you have done most of the Bivec class functions
for example this one:
 ``12345678`` ``````template void Bivec::free() { while (v.size() > 0) { v.pop_back(); } }``````

Now look at the way you have done this Bivec constructor
 ``123456`` ``````Bivec::Bivec (int lo, int hi, T initial_value): v(hi - lo + 1), low(lo) { for (int i = 0; i < static_cast(v.size()); i++) v[i] = new T(initial_value); } template // and what is this line doing here anyway???? ``````

Thanks very much, I think I got too attached to the idea of the constructor being different to member functions (all the examples I looked through had the constructor fully defined in the class definition.

Thanks for putting up with my brain freeze :)
Aside:

I see exception specifiers in the code above. These are pretty much deprecated these days, and to my knowledge have been so for some while. They should be avoided!!

From A Pragmatic Look at Exception Specifications
Herb Sutter
First pub: C/C++ Users Journal, 20(7), July 2002.
http://www.gotw.ca/publications/mill22.htm

 ``` Moral #1: Never write an exception specification. Moral #2: Except possibly an empty one, but if I were you I’d avoid even that.```

Andy
Last edited on
Topic archived. No new replies allowed.