Simple template experiment fails

B

Bert Aerts (rm X)

With following files, the print statement
cout << amt.getElem(2) << endl;
can not be compiled.

Though getElem returns Type, in this case class MyType, which has print
functions defined.

It does work for int and long double types...

What am I missing? Thanks for any help!

/*
* chapter11.h
*
* Created on: Sep 13, 2009
* Author: bert
*/

#ifndef CHAPTER11_H_
#define CHAPTER11_H_

// template defining an array
template <class Type>
class Array
{
public:
Array();
~Array();
void setSize(size_t value);
size_t getSize();
void setElem(size_t index, Type value);
Type getElem(size_t index);
private:
Type *elems;
size_t numElems;
};

// a user-defined type
class MyType
{
public:
MyType();
// a member function that modifies instances of MyType
void sanitize();
void print(ostream *os);
private:
int value;
};

#endif /* CHAPTER11_H_ */


/*
* chapter11.cpp
*
* Created on: Sep 13, 2009
* Author: bert
*/

#include <iostream>
using namespace std;

#include <stdlib.h> // to get exit()
#include "chapter11.h"

#define SIZE 10

template<class Type>
Array<Type>::Array()
{
elems = 0;
numElems = 0;
}

template<class Type>
Array<Type>::~Array()
{
if( elems != 0 )
{
cout << "delete[] " << (void *) elems << endl;
delete[] elems;
}
}

template<class Type>
void Array<Type>::setSize(size_t value)
{
if( elems != 0 ) delete[] elems;
numElems = value;
elems = new Type[value];
if( elems != 0 )
{
cout << "elems pointer is " << (void *)elems << endl;
}
else
{
cout << "new[] failed" << endl;
exit(1);
}
}

template<class Type>
size_t Array<Type>::getSize()
{
return numElems;
}

template<class Type>
void Array<Type>::setElem(size_t index, Type value)
{
if( index < numElems )
{
elems[index] = value;
}
else
{
cout << "setElem bad index " << index << " >= " << numElems << endl;
exit(1);
}
}

template<class Type>
Type Array<Type>::getElem(size_t index)
{
if( index >= numElems )
{
cout << "getElem bad index " << index << " >= " << numElems << endl;
exit(1);
}
else
{
return elems[index];
}
}

void MyType::print(ostream *os)
{
*os << "MyType{" << value << '}';
}

MyType::MyType()
{
value = 0;
}

void MyType::sanitize()
{
value = 22;
}

ostream &operator<<(ostream &os, MyType &theMyType)
{
theMyType.print(&os);
return os;
}

int main()
{
Array<int> ai;
Array<long double> ald;
Array<MyType> amt;
MyType refmt;

ai.setSize(SIZE);
ai.setElem(2,5);
cout << "ai[2] = " << ai.getElem(2) << endl;

ald.setSize(SIZE);
ald.setElem(2,3.1415);
cout << "ald[2] = " << ald.getElem(2) << endl;

amt.setSize(SIZE);
cout << "refmt is " << refmt << endl;
amt.setElem(2,refmt);
cout << amt.getElem(2) << endl; // DOES NOT COMPILE
refmt.sanitize();
cout << "refmt.sanitize gives " << refmt << endl;
}
 
V

Victor Bazarov

Bert said:
With following files, the print statement
cout << amt.getElem(2) << endl;
can not be compiled.

Though getElem returns Type, in this case class MyType, which has print
functions defined.

It does work for int and long double types...

What am I missing? Thanks for any help!

[..]
template<class Type>
Type Array<Type>::getElem(size_t index)
^^^^
Returns by value, yes?
{ [..]
}

[..]
ostream &operator<<(ostream &os, MyType &theMyType)
^^^^^^^^^^
The argument is a reference to non-const, yes?
{
theMyType.print(&os);
return os;
}

int main()
{
> [..]
cout << amt.getElem(2) << endl; // DOES NOT COMPILE

'amt.getElem(2)' returns a temporary, which cannot be bound to a
reference to non-const.

I didn't check what the compiler says, you ought to post the actual
compiler message (do, next time).
refmt.sanitize();
cout << "refmt.sanitize gives " << refmt << endl;
}

V
 
B

Bert Aerts (rm X)

Victor said:
Bert said:
With following files, the print statement
cout << amt.getElem(2) << endl;
can not be compiled.

Though getElem returns Type, in this case class MyType, which has
print functions defined.

It does work for int and long double types...

What am I missing? Thanks for any help!

[..]
template<class Type>
Type Array<Type>::getElem(size_t index)
^^^^
Returns by value, yes?
{ [..]
}

[..]
ostream &operator<<(ostream &os, MyType &theMyType)
^^^^^^^^^^
The argument is a reference to non-const, yes?
{
theMyType.print(&os);
return os;
}

int main()
{
[..]
cout << amt.getElem(2) << endl; // DOES NOT COMPILE

'amt.getElem(2)' returns a temporary, which cannot be bound to a
reference to non-const.

I didn't check what the compiler says, you ought to post the actual
compiler message (do, next time).

The GNU g++ compiler says:
.../chapter11.cpp:123: error: no match for ‘operator<<’ in ‘std::cout <<
amt.Array said:

I solved the issue by following lines
in chapter11.h
Type &getElem(size_t index);
and in chapter11.cpp
template<class Type>
Type &Array<Type>::getElem(size_t index)

returning a reference iso by value.
Now the print works.

Thanks for your reply.
 
V

Victor Bazarov

Bert said:
Victor said:
Bert said:
With following files, the print statement
cout << amt.getElem(2) << endl;
can not be compiled.

Though getElem returns Type, in this case class MyType, which has
print functions defined.

It does work for int and long double types...

What am I missing? Thanks for any help!

[..]
template<class Type>
Type Array<Type>::getElem(size_t index)
^^^^
Returns by value, yes?
{ [..]
}

[..]
ostream &operator<<(ostream &os, MyType &theMyType)
^^^^^^^^^^
The argument is a reference to non-const, yes?
{
theMyType.print(&os);
return os;
}

int main()
{
[..]
cout << amt.getElem(2) << endl; // DOES NOT COMPILE

'amt.getElem(2)' returns a temporary, which cannot be bound to a
reference to non-const.

I didn't check what the compiler says, you ought to post the actual
compiler message (do, next time).

The GNU g++ compiler says:
../chapter11.cpp:123: error: no match for ‘operator<<’ in ‘std::cout <<
amt.Array said:

I solved the issue by following lines
in chapter11.h
Type &getElem(size_t index);
and in chapter11.cpp
template<class Type>
Type &Array<Type>::getElem(size_t index)

returning a reference iso by value.
Now the print works.

Or, you could have solved it by making 'print' a const member and making
operator<< accept a reference to const as its second argument. Read up
on "const correctness".

V
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,736
Latest member
AdolphBig6

Latest Threads

Top