473,237 Members | 1,399 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,237 software developers and data experts.

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

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
1 3301
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

699
by: mike420 | last post by:
I think everyone who used Python will agree that its syntax is the best thing going for it. It is very readable and easy for everyone to learn. But, Python does not a have very good macro...
4
by: Tomas Ukkonen | last post by:
Hi I'm currently trying to make my old code to compile with new gcc 3.4.0. It compiles correctly in 3.3.3 so I'm not sure if this is compiler bug or not. Code very close to a example below...
8
by: Rich Grise | last post by:
I think I've finally found a tutorial that can get me started: http://www.zib.de/Visual/people/mueller/Course/Tutorial/tutorial.html and I've been lurking for awhile as well. What happened is,...
2
by: paul-henri.ferme | last post by:
Hi all, I just hit the following definition in a c++ API: template <class Str> template <class T, class B> mysql_ColData<Str>::operator Null<T,B> () const { if ((*this) == 'N' && (*this) ==...
7
by: Mark P | last post by:
Is this legal and sensible? class Outer { friend struct Inner { ... }; ...
6
by: Howard | last post by:
Hi, I have a function in three unrelated but similar classes. The code in the member functions is identical for all three classes. What I want is to make a template which defines the function,...
4
by: noone | last post by:
Hi. I've got a fella working for me who is trying to convince me to change our coding standards to using separate .h and .cc files for definitions and implementations. I know this is a...
2
by: andrew_nuss | last post by:
Hi, I have an Array<Ttemplate that specializes on T's in my program that inherit from a base class that I've defined called CtorDtorLess. In my array template, I check if...
2
by: Andy Champ | last post by:
We have a class with something that, simplified, looks like this: template <typename Tclass foo { T beyondAllReaching; // In VC2005, this works OK template <typename Ufriend void...
3
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 3 Jan 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). For other local times, please check World Time Buddy In...
0
by: jianzs | last post by:
Introduction Cloud-native applications are conventionally identified as those designed and nurtured on cloud infrastructure. Such applications, rooted in cloud technologies, skillfully benefit from...
0
by: abbasky | last post by:
### Vandf component communication method one: data sharing ​ Vandf components can achieve data exchange through data sharing, state sharing, events, and other methods. Vandf's data exchange method...
0
by: fareedcanada | last post by:
Hello I am trying to split number on their count. suppose i have 121314151617 (12cnt) then number should be split like 12,13,14,15,16,17 and if 11314151617 (11cnt) then should be split like...
0
by: stefan129 | last post by:
Hey forum members, I'm exploring options for SSL certificates for multiple domains. Has anyone had experience with multi-domain SSL certificates? Any recommendations on reliable providers or specific...
0
Git
by: egorbl4 | last post by:
Скачал я git, хотел начать настройку, а там вылезло вот это Что это? Что мне с этим делать? ...
0
by: MeoLessi9 | last post by:
I have VirtualBox installed on Windows 11 and now I would like to install Kali on a virtual machine. However, on the official website, I see two options: "Installer images" and "Virtual machines"....
0
by: Aftab Ahmad | last post by:
Hello Experts! I have written a code in MS Access for a cmd called "WhatsApp Message" to open WhatsApp using that very code but the problem is that it gives a popup message everytime I clicked on...
0
by: Aftab Ahmad | last post by:
So, I have written a code for a cmd called "Send WhatsApp Message" to open and send WhatsApp messaage. The code is given below. Dim IE As Object Set IE =...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.