| Topic: |
DEVELOP > c-Plus-Plus |
| User: |
"=?ISO-8859-1?Q?Christian_Brechb=FChler?=" |
| Date: |
19 Oct 2003 11:44:16 AM |
| Object: |
Arithmetic conversions/promotion and templates |
Let me use complex numbers as a familiar example. The following is
taken verbatim from Bjarne Stroustrup, "The C++ Programming Language",
except the include line and the "no match" comments. It won't compile.
#include <complex>
// section 22.5:
// Throughout this book, I have used complex as a class rather than as a
// template. This is feasible because I assumed a bit of namespace magic to
// get the complex of double that I usually prefer:
typedef std::complex<double> complex;
// section 11.3:
// For example, from looking at a math textbook we would expect this to
work:
void f()
{
complex a = complex(1,2);
complex b = 3;
complex c = a+2.3;
complex d = 2+b; // no match for `int + complex&' operator
complex e = -b-c;
b = c*2*c; // no match for `complex& * int' operator
}
(Obviously we could kludge it by replacing 2 by 2.0 or double(2) etc.,
but I think we rightfully expect it to work exactly as Stroustrup wrote it.)
Questions: What was the rationale for implementing the standard library
like this?
Is there a generic way to accept any type that the usual arithmetic
conversions (C.6.3) can promote to double as the left or right argument
to a binary operator?
(I tried templating on the "simple" type, but when I do it for the left
and right argument, a+b becomes ambiguous. -- I there a way to express
that a template parameter "class T" must have a conversion to double?)
Thanks
Christian
.
|
|
| User: "Victor Bazarov" |
|
| Title: Re: Arithmetic conversions/promotion and templates |
19 Oct 2003 12:26:38 PM |
|
|
"Christian Brechbühler" <c_brechbuehler@yhaoo.com> wrote...
Let me use complex numbers as a familiar example. The following is
taken verbatim from Bjarne Stroustrup, "The C++ Programming Language",
except the include line and the "no match" comments. It won't compile.
#include <complex>
// section 22.5:
// Throughout this book, I have used complex as a class rather than as a
// template. This is feasible because I assumed a bit of namespace magic
to
// get the complex of double that I usually prefer:
typedef std::complex<double> complex;
// section 11.3:
// For example, from looking at a math textbook we would expect this to
work:
void f()
{
complex a = complex(1,2);
complex b = 3;
complex c = a+2.3;
complex d = 2+b; // no match for `int + complex&' operator
complex e = -b-c;
b = c*2*c; // no match for `complex& * int' operator
}
(Obviously we could kludge it by replacing 2 by 2.0 or double(2) etc.,
but I think we rightfully expect it to work exactly as Stroustrup wrote
it.)
Questions: What was the rationale for implementing the standard library
like this?
This is a question for comp.std.c++. They discuss the "why" questions.
We here discuss the "how".
Is there a generic way to accept any type that the usual arithmetic
conversions (C.6.3) can promote to double as the left or right argument
to a binary operator?
Yes.
#include <complex>
typedef std::complex<double> complex;
template<class T>
complex operator +(const complex& c, T t) {
return std::operator +(c,complex(t)); // call the std:: one
}
void foo() {
complex a(1,2);
complex b = 2 + a; // ours works fine
}
(I tried templating on the "simple" type, but when I do it for the left
and right argument, a+b becomes ambiguous. -- I there a way to express
that a template parameter "class T" must have a conversion to double?)
I am not sure what you're saying here. Please supply the code.
Victor
.
|
|
|
| User: "=?ISO-8859-1?Q?Christian_Brechb=FChler?=" |
|
| Title: Re: Arithmetic conversions/promotion and templates |
19 Oct 2003 11:00:56 PM |
|
|
Victor Bazarov wrote:
"Christian Brechbühler" <c_brechbuehler@yhaoo.com> wrote...
Is there a generic way to accept any type that the usual arithmetic
conversions (C.6.3) can promote to double as the left or right argument
to a binary operator?
Yes.
#include <complex>
typedef std::complex<double> complex;
template<class T>
complex operator +(const complex& c, T t) {
return std::operator +(c,complex(t)); // call the std:: one
}
void foo() {
complex a(1,2);
complex b = 2 + a; // ours works fine
}
Cool, thanks! I see it works, but how? With T=int, your definition
explicitly defines the operator complex + int. But apparently at the
same time it defines int + complex!
Your definition supports 2 + a and a + 2. Why?
I had tried something that looks superficially the same, except it
doesn't use typedef:
#include <complex>
template<class T, class Real>
std::complex<Real> operator +(const std::complex<Real>& c, T t) {
return std::operator +(c,std::complex<Real>(t));
}
void foo() {
std::complex<double> a(1,2);
std::complex<double> b = 2 + a; // error: no match
std::complex<double> c = a + 2;
}
And here only one of the operators gets defined.
Thanks again to Victor for the quick and neat answer!
Christian
.
|
|
|
|
|
| User: "Gianni Mariani" |
|
| Title: Re: Arithmetic conversions/promotion and templates |
19 Oct 2003 12:59:52 PM |
|
|
Christian Brechbühler wrote:
Questions: What was the rationale for implementing the standard library
like this?
I don't know.
Is there a generic way to accept any type that the usual arithmetic
conversions (C.6.3) can promote to double as the left or right argument
to a binary operator?
(I tried templating on the "simple" type, but when I do it for the left
and right argument, a+b becomes ambiguous. -- I there a way to express
that a template parameter "class T" must have a conversion to double?)
I think you may need to be more generic with your example because
you can supply your own operators that solves the complex problem.
template <typename T>
inline complex<T> operator+ (
const typename complex<T>::value_type & r,
const complex<T> & c
)
{
return complex<T>( r, 0 ) + c;
}
template <typename T>
inline complex<T> operator* (
const complex<T> & c,
const typename complex<T>::value_type & r
)
{
return c * complex<T>( r, 0 );
}
.
|
|
|
|

|
Related Articles |
|
|