By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
425,749 Members | 1,615 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 425,749 IT Pros & Developers. It's quick & easy.

Correct syntax for definitions of inner classes of a template class.

P: n/a
Hi,

I'm learning C++ as a hobby using The C++ Programming Language : Special
Edition by Bjarne Stroustrup. I'm working on chpater 13 exercises that
deal with templates. Exercise 13.9[4] asks for me to turn a previously
made String class that deals with char's into a templated String class
that uses the template parameter C instead of char. I thought it would
be fairly simple to do this exercise, but I encoutered many errors for
my defintions of the inner class Srep, and Cref because they are defined
outside the class. The classes are String::Srep, and String::Cref, and
were defined previously as struct String::Srep { /* ... */ }; And now
there are many errors after trying to template my String class.

Would any of you mind explaining why the following does not work? My
text does not have any examples on how to define templated inner classes
and friend functions.

The errors in the following code were all created after trying to
template my previously working String class. So, only the way I
templated it should be in error.

I'd appreciate any help that any of you can render.

Thanks, Oplec.

/*
Solution to 13.9[4] of The C++ Programming Language :
Special Edition.

Oplec

October 26, 2003

Exercise 13.9[4]:
Complete the String template from 13.2 based on the String
class from 11.12.

Note:
This source has been modified from 11.14[11].
I have been unsuccessful in discovering the correct
syntax for defining the templated definitions of the
inner classes of class String, as well for the
friend functions. Many, many compile-time errors
are reported in regards to ISO, friend, parse, et cetera.

Method used:
1) I used the original String class that I made for
11.14[11] and began by replacing each "char" with
the template parameter "C".
2) Added "template<class C>" above "class String".
3) Copied the definitions from string.cpp to string.h
because my compiler does not support export.
4) Replaced "String::" with "template<class C> String<C>::"
5) Replaced "String&" with "String<C>&"
6) Turned class Subtring into a template class
7) Replaced the return type "Substring" with "Substring<C>"
8) Replaced "friend" with "friend template<class T>"
*/

#ifndef STRING_H
#define STRING_H

#include <string>
#include <iostream>

// Forward declaration for use in String.
template<class C> class Substring;

template<class C>
class String {
struct Srep;
Srep *rep;
public:
class Cref;

struct Range;

friend class Substring;

String();
String(const C*);
String(const String<C>&);
String<C>& operator=(const C*);
String<C>& operator=(const String<C>&);
~String();

const C* c_str() const;
bool find(const String<C>&, int*, int*) const;
void check(int i) const;

C read(int i) const;
void write(int i, C c);

Cref operator[](int i);
C operator[](int i) const;
Substring<C> operator()(int i, int j);
int size() const;

String<C>& operator+=(const String<C>&);
String<C>& operator+=(const C*);

friend template<class T>
std::ostream& operator<<(std::ostream&, const String<T>&);
//friend std::istream& operator>>(std::istream&, const String<C>&);

friend template<class T>
bool operator==(const String<T>& x, const T* s);

friend template<class T>
bool operator==(const String<T>& x, const String<T>& y);

friend template<class T>
bool operator!=(const String<T>& x, const T* s);

friend template<class T>
bool operator!=(const String<T>& x, const String<T>& y);
};

template<class C>
struct String<C>::Range {
String s;
Range(const String<C>& p) :s(p) { }
};

template<class C>
struct String<C>::Srep {
C* s;
int sz;
int n;

Srep(int nsz, const C* p) : n(1), sz(nsz)
{
s = new C[sz+1];
std::strcpy(s,p);
}

~Srep() { delete[] s; }

Srep* get_own_copy()
{
if (n==1) return this;
n--;
return new Srep(sz, s);
}

void assign(int nsz, const C* p)
{
if (sz != nsz) {
delete[] s;
sz = nsz;
s = new C[sz+1];
}
std::strcpy(s,p);
}

private:
Srep(const Srep&);
Srep& operator=(const Srep&);
};

template<class C>
class String<C>::Cref {
friend class String;
String<C>& s;
int i;
Cref(String<C>& ss, int ii) : s(ss), i(ii) {}

public:
operator C() const { return s.read(i); }
void operator=(C c) { s.write(i,c); }
};

// Substring class for refering to a substring of String
// and replacing it with another String.
// i, j are indexes for the substring.
// Contents of the substring include from position i up to,
// but not including j.
//
// String s = "1234567890";
// "1234" == s(0,5)
template<class C>
class Substring {
String<C>& s;
int i, j;
public:
Substring(int x, int y, String<C>& p)
:i(x), j(y), s(p) { }

Substring(const SubString<C>& ss)
:s(ss.s), i(ss.i), j(ss.j) { }

operator String() const
{
String p;
C buff[2];
buff[1] = 0;
for (int k=i; k<j; k++) {
buff[0] = s[k];
p += buff;
}
return p;
}

void operator=(const String<C>& x)
{
String p;
p += s(0,i);
p += x;
p += s(j,s.rep->sz);

s = p;
}
};

/*
CLASS TEMPLATE MEMBER DEFINITIONS
*/
template<class C>
String<C>::String()
{
rep = new Srep(0,"");
}

template<class C>
String<C>::String(const String<C>& x)
{
x.rep->n++;
rep = x.rep;
}

template<class C>
String<C>::~String()
{
if (--rep->n == 0) delete rep;
}

// Chapter 11, Exercise 10 addition
template<class C>
const C* String<C>::c_str() const { return rep->s; }

// Chapter 11, Exercise 11 addition
template<class C>
bool String<C>::find(const String<C>& s, int* i, int* j) const
{
int k=0;
while (k <= rep->sz) {
int m = k;
int l = 0;
while (l < s.rep->sz && m < rep->sz && read(m) == s[l]) {
m++;
l++;
}
if (l >= s.rep->sz) {
*i = k;
*j = m;
return true;
}
k++;
}

return false;
}

template<class C>
String<C>& String<C>::operator=(const String<C>& x)
{
x.rep->n++;
if (--rep->n == 0) delete rep;
rep = x.rep;
return *this;
}

template<class C>
String<C>::String(const C* s)
{
rep = new Srep(std::strlen(s),s);
}

template<class C>
String<C>& String<C>::operator=(const C* s)
{
if (rep->n == 1)
rep->assign(std::strlen(s),s);
else {
if (--rep->n == 0) delete rep;
rep = new Srep(std::strlen(s),s);
}
return *this;
}

template<class C>
String<C>& String<C>::operator+=(const String<C>& x)
{
int nsz = std::strlen(x.rep->s) + std::strlen(rep->s);
C* ns = new C[nsz+1];
std::strcpy(ns,rep->s);
std::strcat(ns,x.rep->s);

if (rep->n == 1)
rep->assign(nsz, ns);
else {
if (--rep->n == 0) delete rep;
rep = new Srep(nsz, ns);
}
delete[] ns;
return *this;
}

template<class C>
String<C>& String<C>::operator+=(const C* s)
{
int nsz = std::strlen(s) + std::strlen(rep->s);
C* ns = new C[nsz+1];
std::strcpy(ns,rep->s);
std::strcat(ns,s);

if (rep->n == 1)
rep->assign(nsz, ns);
else {
if (--rep->n == 0) delete rep;
rep = new Srep(nsz, ns);
}
delete[] ns;
return *this;
}

template<class T>
std::ostream& operator<<(std::ostream& os, const String<T>& s)
{
for (int i=0; i < s.rep->sz; ++i)
std::cout << s.rep->s[i];

return os;
}

template<class C>
void String<C>::check(int i) const
{
if (i<0 || rep->sz<=i) throw Range(*this);
}

template<class C>
C String<C>::read(int i) const { return rep->s[i]; }

template<class C>
void String<C>::write(int i, C c) { rep=rep->get_own_copy(); rep->s[i]=c; }

template<class C>
String<C>::Cref String<C>::operator[](int i) { check(i); return
Cref(*this,i); }

template<class C>
C String<C>::operator[](int i) const { check(i); return rep->s[i]; }

// Chapter 11, Exercise 8-9 addition
template<class C>
Substring<C> String<C>::operator()(int i, int j)
{
return Substring<C>(i,j,*this);
}

template<class C>
int String<C>::size() const { return rep->sz; }

template<class T>
bool operator==(const String<T>& x, const T* s)
{
return std::strcmp(x.rep->s, s) == 0;
}

template<class T>
bool operator==(const String<T>& x, const String<T>& y)
{
return std::strcmp(x.rep->s, y.rep->s) == 0;
}

template<class T>
bool operator!=(const String<T>& x, const T* s)
{
return std::strcmp(x.rep->s, s) != 0;
}

template<class T>
bool operator!=(const String<T>& x, const String<T>& y)
{
return std::strcmp(x.rep->s, y.rep->s) != 0;
}

#endif // STRING_H

Jul 19 '05 #1
Share this Question
Share on Google+
1 Reply


P: n/a
Oplec ??:
Hi,

I'm learning C++ as a hobby using The C++ Programming Language : Special
Edition by Bjarne Stroustrup. I'm working on chpater 13 exercises that
deal with templates. Exercise 13.9[4] asks for me to turn a previously
made String class that deals with char's into a templated String class
that uses the template parameter C instead of char. I thought it would
be fairly simple to do this exercise, but I encoutered many errors for
my defintions of the inner class Srep, and Cref because they are defined
outside the class. The classes are String::Srep, and String::Cref, and
were defined previously as struct String::Srep { /* ... */ }; And now
there are many errors after trying to template my String class.

Would any of you mind explaining why the following does not work? My
text does not have any examples on how to define templated inner classes
and friend functions.

The errors in the following code were all created after trying to
template my previously working String class. So, only the way I
templated it should be in error.

I'd appreciate any help that any of you can render.

Thanks, Oplec.

/*
Solution to 13.9[4] of The C++ Programming Language :
Special Edition.

Oplec

October 26, 2003

Exercise 13.9[4]:
Complete the String template from 13.2 based on the String
class from 11.12.

Note:
This source has been modified from 11.14[11].
I have been unsuccessful in discovering the correct
syntax for defining the templated definitions of the
inner classes of class String, as well for the
friend functions. Many, many compile-time errors
are reported in regards to ISO, friend, parse, et cetera.

Method used:
1) I used the original String class that I made for
11.14[11] and began by replacing each "char" with
the template parameter "C".
2) Added "template<class C>" above "class String".
3) Copied the definitions from string.cpp to string.h
because my compiler does not support export.
4) Replaced "String::" with "template<class C> String<C>::"
5) Replaced "String&" with "String<C>&"
6) Turned class Subtring into a template class
7) Replaced the return type "Substring" with "Substring<C>"
8) Replaced "friend" with "friend template<class T>"
*/

#ifndef STRING_H
#define STRING_H

#include <string>
#include <iostream>

// Forward declaration for use in String.
template<class C> class Substring;

template<class C>
class String {
struct Srep;
Srep *rep;
public:
class Cref;

struct Range;

friend class Substring;

String();
String(const C*);
String(const String<C>&);
String<C>& operator=(const C*);
String<C>& operator=(const String<C>&);
~String();

const C* c_str() const;
bool find(const String<C>&, int*, int*) const;
void check(int i) const;

C read(int i) const;
void write(int i, C c);

Cref operator[](int i);
C operator[](int i) const;
Substring<C> operator()(int i, int j);
int size() const;

String<C>& operator+=(const String<C>&);
String<C>& operator+=(const C*);

friend template<class T>
std::ostream& operator<<(std::ostream&, const String<T>&);
//friend std::istream& operator>>(std::istream&, const String<C>&);

friend template<class T>
bool operator==(const String<T>& x, const T* s);

friend template<class T>
bool operator==(const String<T>& x, const String<T>& y);

friend template<class T>
bool operator!=(const String<T>& x, const T* s);

friend template<class T>
bool operator!=(const String<T>& x, const String<T>& y);
};

template<class C>
struct String<C>::Range {
String s;
Range(const String<C>& p) :s(p) { }
};

template<class C>
struct String<C>::Srep {
C* s;
int sz;
int n;

Srep(int nsz, const C* p) : n(1), sz(nsz)
{
s = new C[sz+1];
std::strcpy(s,p);
}

~Srep() { delete[] s; }

Srep* get_own_copy()
{
if (n==1) return this;
n--;
return new Srep(sz, s);
}

void assign(int nsz, const C* p)
{
if (sz != nsz) {
delete[] s;
sz = nsz;
s = new C[sz+1];
}
std::strcpy(s,p);
}

private:
Srep(const Srep&);
Srep& operator=(const Srep&);
};

template<class C>
class String<C>::Cref {
friend class String;
String<C>& s;
int i;
Cref(String<C>& ss, int ii) : s(ss), i(ii) {}

public:
operator C() const { return s.read(i); }
void operator=(C c) { s.write(i,c); }
};

// Substring class for refering to a substring of String
// and replacing it with another String.
// i, j are indexes for the substring.
// Contents of the substring include from position i up to,
// but not including j.
//
// String s = "1234567890";
// "1234" == s(0,5)
template<class C>
class Substring {
String<C>& s;
int i, j;
public:
Substring(int x, int y, String<C>& p)
:i(x), j(y), s(p) { }

Substring(const SubString<C>& ss)
:s(ss.s), i(ss.i), j(ss.j) { }

operator String() const
{
String p;
C buff[2];
buff[1] = 0;
for (int k=i; k<j; k++) {
buff[0] = s[k];
p += buff;
}
return p;
}

void operator=(const String<C>& x)
{
String p;
p += s(0,i);
p += x;
p += s(j,s.rep->sz);

s = p;
}
};

/*
CLASS TEMPLATE MEMBER DEFINITIONS
*/
template<class C>
String<C>::String()
{
rep = new Srep(0,"");
}

template<class C>
String<C>::String(const String<C>& x)
{
x.rep->n++;
rep = x.rep;
}

template<class C>
String<C>::~String()
{
if (--rep->n == 0) delete rep;
}

// Chapter 11, Exercise 10 addition
template<class C>
const C* String<C>::c_str() const { return rep->s; }

// Chapter 11, Exercise 11 addition
template<class C>
bool String<C>::find(const String<C>& s, int* i, int* j) const
{
int k=0;
while (k <= rep->sz) {
int m = k;
int l = 0;
while (l < s.rep->sz && m < rep->sz && read(m) == s[l]) {
m++;
l++;
}
if (l >= s.rep->sz) {
*i = k;
*j = m;
return true;
}
k++;
}

return false;
}

template<class C>
String<C>& String<C>::operator=(const String<C>& x)
{
x.rep->n++;
if (--rep->n == 0) delete rep;
rep = x.rep;
return *this;
}

template<class C>
String<C>::String(const C* s)
{
rep = new Srep(std::strlen(s),s);
}

template<class C>
String<C>& String<C>::operator=(const C* s)
{
if (rep->n == 1)
rep->assign(std::strlen(s),s);
else {
if (--rep->n == 0) delete rep;
rep = new Srep(std::strlen(s),s);
}
return *this;
}

template<class C>
String<C>& String<C>::operator+=(const String<C>& x)
{
int nsz = std::strlen(x.rep->s) + std::strlen(rep->s);
C* ns = new C[nsz+1];
std::strcpy(ns,rep->s);
std::strcat(ns,x.rep->s);

if (rep->n == 1)
rep->assign(nsz, ns);
else {
if (--rep->n == 0) delete rep;
rep = new Srep(nsz, ns);
}
delete[] ns;
return *this;
}

template<class C>
String<C>& String<C>::operator+=(const C* s)
{
int nsz = std::strlen(s) + std::strlen(rep->s);
C* ns = new C[nsz+1];
std::strcpy(ns,rep->s);
std::strcat(ns,s);

if (rep->n == 1)
rep->assign(nsz, ns);
else {
if (--rep->n == 0) delete rep;
rep = new Srep(nsz, ns);
}
delete[] ns;
return *this;
}

template<class T>
std::ostream& operator<<(std::ostream& os, const String<T>& s)
{
for (int i=0; i < s.rep->sz; ++i)
std::cout << s.rep->s[i];

return os;
}

template<class C>
void String<C>::check(int i) const
{
if (i<0 || rep->sz<=i) throw Range(*this);
}

template<class C>
C String<C>::read(int i) const { return rep->s[i]; }

template<class C>
void String<C>::write(int i, C c) { rep=rep->get_own_copy(); rep->s[i]=c; }

template<class C>
String<C>::Cref String<C>::operator[](int i) { check(i); return
Cref(*this,i); }

template<class C>
C String<C>::operator[](int i) const { check(i); return rep->s[i]; }

// Chapter 11, Exercise 8-9 addition
template<class C>
Substring<C> String<C>::operator()(int i, int j)
{
return Substring<C>(i,j,*this);
}

template<class C>
int String<C>::size() const { return rep->sz; }

template<class T>
bool operator==(const String<T>& x, const T* s)
{
return std::strcmp(x.rep->s, s) == 0;
}

template<class T>
bool operator==(const String<T>& x, const String<T>& y)
{
return std::strcmp(x.rep->s, y.rep->s) == 0;
}

template<class T>
bool operator!=(const String<T>& x, const T* s)
{
return std::strcmp(x.rep->s, s) != 0;
}

template<class T>
bool operator!=(const String<T>& x, const String<T>& y)
{
return std::strcmp(x.rep->s, y.rep->s) != 0;
}

#endif // STRING_H


Jul 19 '05 #2

This discussion thread is closed

Replies have been disabled for this discussion.