F
franky.backeljauw
Hello,
I have a problem with using a copy constructor to convert an object of a
templated class to object of another templated class. Let me first
include the code (my question is below):
<code:templates.h>
#include <string>
#include <iostream>
using namespace std;
template<class T> class tempo;
template<class T>
class delo
{
private:
tempo<T> a;
tempo<T> b;
public:
delo () : a(0), b(0) {}
delo ( T c, T d ) : a(c), b(d) {}
void evaluate( tempo<T>& c );
};
template<class T> void printValue( tempo<T> );
template<class T> ostream& operator<< ( ostream&, const tempo<T>& );
template <class T>
class tempo
{
private:
T value;
public:
tempo () : value(0) {}
tempo ( T init ) : value(init) {}
tempo ( delo<T> d ) { d.evaluate(*this); }
friend ostream& operator<< <T>( ostream&, const tempo& );
void compute( tempo& a, tempo& b );
};
template class delo<int>;
template class tempo<int>;
</code:templates.h>
<code:templates.cpp>
#include "templates.h"
#include <iostream>
template <class T>
void delo<T>::evaluate( tempo<T>& c )
{
c.compute( a, b );
}
template <class T>
void tempo<T>::compute( tempo<T>& a, tempo<T>& b )
{
value = a.value + b.value;
}
template <class T>
ostream& operator<< ( ostream& o, const tempo<T>& t )
{
o << "current value = " << t.value << endl;
return o;
}
template ostream& operator<< ( ostream&, const tempo<int>& );
</code:templates.cpp>
The class "delo" is used to delay the computation (compute, in this
example an addition) until it needs to be executed, e.g. when a left-side
object is given or when the result is requested for instance using cout.
In this case, the "delo" object should be converted to a "tempo" object
using the copy constructor, which calls the evaluate function, in which
the compute function is actually called.
So far, so good ... now look at a test program:
<code:test.cpp>
#include "templates.h"
#include <iostream>
using namespace std;
int main ()
{
tempo<int> anInt( 123 );
cout << anInt << endl;
delo<int> aDelInt( 789, 211 );
cout << aDelInt << endl;
}
</code:test.cpp>
The first cout line compiles without any problem, but the second cout line
results in a long error message, which goes like:
<error>
g++ -c test.cpp -o test.o
test.cpp: In function `int main()':
test.cpp:19: no match for `std:stream& << delo<int>&' operator
/usr/include/c++/3.2.2/bits/ostream.tcc:55: candidates are:
std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT,
_Traits>:perator<<(std::basic_ostream<_CharT,
_Traits>&(*)(std::basic_ostream<_CharT, _Traits>&)) [with
_CharT = char,
_Traits = std::char_traits<char>]
/usr/include/c++/3.2.2/bits/ostream.tcc:77:
std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT,
_Traits>:perator<<(std::basic_ios<_CharT,
_Traits>&(*)(std::basic_ios<_CharT, _Traits>&)) [with _CharT =
char, _Traits
= std::char_traits<char>]
/usr/include/c++/3.2.2/bits/ostream.tcc:99:
std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT,
_Traits>:perator<<(std::ios_base&(*)(std::ios_base&)) [with
_CharT = char,
_Traits = std::char_traits<char>]
/usr/include/c++/3.2.2/bits/ostream.tcc:171:
std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT,
_Traits>:perator<<(long int) [with _CharT = char, _Traits =
std::char_traits<char>]
[...]
/usr/include/c++/3.2.2/ostream:211:
std::basic_ostream<_CharT,
_Traits>& std:perator<<(std::basic_ostream<_CharT, _Traits>&,
char) [with
_CharT = char, _Traits = std::char_traits<char>]
make: *** [test.o] Error 1
</error>
This says it cannot output the "delo" object, while it could copy this
object to a "tempo" object using the copy constructor. But it seems like
it does not know about this copy constructor, or that it cannot use it.
Copying it explicitly (that is, using "cout << tempo<int>( aDelInt )" in
test.cpp does work.
If I use non-templated versions of these classes, it works fine and it
calls the copy constructor like it should.
So my questions are: why does this give an error, and why is it not using
the copy constructor? Are there any limitations? And if so, is there
another way to solve this (without having to do it myself explicitly)?
-- Thanks for any reply.
Franky Backeljauw
University of Antwerp
Department of Mathematics and Computer Science
I have a problem with using a copy constructor to convert an object of a
templated class to object of another templated class. Let me first
include the code (my question is below):
<code:templates.h>
#include <string>
#include <iostream>
using namespace std;
template<class T> class tempo;
template<class T>
class delo
{
private:
tempo<T> a;
tempo<T> b;
public:
delo () : a(0), b(0) {}
delo ( T c, T d ) : a(c), b(d) {}
void evaluate( tempo<T>& c );
};
template<class T> void printValue( tempo<T> );
template<class T> ostream& operator<< ( ostream&, const tempo<T>& );
template <class T>
class tempo
{
private:
T value;
public:
tempo () : value(0) {}
tempo ( T init ) : value(init) {}
tempo ( delo<T> d ) { d.evaluate(*this); }
friend ostream& operator<< <T>( ostream&, const tempo& );
void compute( tempo& a, tempo& b );
};
template class delo<int>;
template class tempo<int>;
</code:templates.h>
<code:templates.cpp>
#include "templates.h"
#include <iostream>
template <class T>
void delo<T>::evaluate( tempo<T>& c )
{
c.compute( a, b );
}
template <class T>
void tempo<T>::compute( tempo<T>& a, tempo<T>& b )
{
value = a.value + b.value;
}
template <class T>
ostream& operator<< ( ostream& o, const tempo<T>& t )
{
o << "current value = " << t.value << endl;
return o;
}
template ostream& operator<< ( ostream&, const tempo<int>& );
</code:templates.cpp>
The class "delo" is used to delay the computation (compute, in this
example an addition) until it needs to be executed, e.g. when a left-side
object is given or when the result is requested for instance using cout.
In this case, the "delo" object should be converted to a "tempo" object
using the copy constructor, which calls the evaluate function, in which
the compute function is actually called.
So far, so good ... now look at a test program:
<code:test.cpp>
#include "templates.h"
#include <iostream>
using namespace std;
int main ()
{
tempo<int> anInt( 123 );
cout << anInt << endl;
delo<int> aDelInt( 789, 211 );
cout << aDelInt << endl;
}
</code:test.cpp>
The first cout line compiles without any problem, but the second cout line
results in a long error message, which goes like:
<error>
g++ -c test.cpp -o test.o
test.cpp: In function `int main()':
test.cpp:19: no match for `std:stream& << delo<int>&' operator
/usr/include/c++/3.2.2/bits/ostream.tcc:55: candidates are:
std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT,
_Traits>:perator<<(std::basic_ostream<_CharT,
_Traits>&(*)(std::basic_ostream<_CharT, _Traits>&)) [with
_CharT = char,
_Traits = std::char_traits<char>]
/usr/include/c++/3.2.2/bits/ostream.tcc:77:
std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT,
_Traits>:perator<<(std::basic_ios<_CharT,
_Traits>&(*)(std::basic_ios<_CharT, _Traits>&)) [with _CharT =
char, _Traits
= std::char_traits<char>]
/usr/include/c++/3.2.2/bits/ostream.tcc:99:
std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT,
_Traits>:perator<<(std::ios_base&(*)(std::ios_base&)) [with
_CharT = char,
_Traits = std::char_traits<char>]
/usr/include/c++/3.2.2/bits/ostream.tcc:171:
std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT,
_Traits>:perator<<(long int) [with _CharT = char, _Traits =
std::char_traits<char>]
[...]
/usr/include/c++/3.2.2/ostream:211:
std::basic_ostream<_CharT,
_Traits>& std:perator<<(std::basic_ostream<_CharT, _Traits>&,
char) [with
_CharT = char, _Traits = std::char_traits<char>]
make: *** [test.o] Error 1
</error>
This says it cannot output the "delo" object, while it could copy this
object to a "tempo" object using the copy constructor. But it seems like
it does not know about this copy constructor, or that it cannot use it.
Copying it explicitly (that is, using "cout << tempo<int>( aDelInt )" in
test.cpp does work.
If I use non-templated versions of these classes, it works fine and it
calls the copy constructor like it should.
So my questions are: why does this give an error, and why is it not using
the copy constructor? Are there any limitations? And if so, is there
another way to solve this (without having to do it myself explicitly)?
-- Thanks for any reply.
Franky Backeljauw
University of Antwerp
Department of Mathematics and Computer Science