Topic: specialising std::complex
Author: "kwikius" <andy@servocomm.freeserve.co.uk>
Date: Mon, 17 Jul 2006 09:02:58 CST Raw View
Suppose I have three classes resistance, current and voltage
resistance r = voltage() / current();
However I can also have complex resistances, currents and voltages:
std::complex<resistance> z
= std::complex<voltage>() / std::complex<current>();
(I would have to specialise std::complex for these types)
However the std:: signature for complex multiplication looks like so:
complex<T> operator/ (complex<T> const &, complex<T> const &);
whereas my version would look like (using a simulated typeof):
complex<typeof(T1() / T2()) > operator/ (complex<T1> const &,
complex<T2> const &);
Am I allowed to specialise this in std?
regards
Andy Little
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Richard Smith" <richard@ex-parrot.com>
Date: Mon, 17 Jul 2006 10:59:49 CST Raw View
kwikius wrote:
> Suppose I have three classes resistance, current and voltage
>
> resistance r = voltage() / current();
>
> However I can also have complex resistances, currents and voltages:
>
> std::complex<resistance> z
> = std::complex<voltage>() / std::complex<current>();
>
> (I would have to specialise std::complex for these types)
Yes. You can specialise almost any standard library component:
[17.4.3.1] "A program may add template specializations for any standard
library template to namespace std. Such a specialization (complete or
partial) of a standard library template results in undefined behaviour
unless the declaration depends on a user-defined name ..."
Unfortunately this isn't sufficient as you also have to deal with the
namespace-scope operators such as operator/. As you are not allowed to
inject overloads (only specialisations) into namespace std, and you
cannot partially specialise a function template, this has to be done
some other way. Fortunately ADL provides a way of doing this:
namespace myns {
template <typename T, int Kg, int M, int S, int A>
struct dimension;
typedef dimension<double, 0,0,0,1> current;
typedef dimension<double, 1,2,-3,-1> voltage;
typedef dimension<double, 1,2,-3,-2> resistance;
template <typename T, int Kg1, int M1, int S1, int A1,
int Kg2, int M2, int S2, int A2>
std::complex< dimension<T, Kg1-Kg2, M1-M2, S1-S2, A1-A2> >
operator/( std::complex< dimension<T, Kg1, M1, S1, A1> > const&,
std::complex< dimension<T, Kg2, M2, S2, A2> > const& );
template <typename T, int Kg, int M, int S, int A>
std::complex<T>
operator/( std::complex< dimension<T, Kg, M, S, A> > const&,
std::complex< dimension<T, Kg, M, S, A> > const& );
}
int main() {
std::complex< myns::voltage > V;
std::complex< myns::current > I;
std::complex< myns::resistance > Z = V/I;
std::complex< double > U = I/I;
}
The second operator/ overload is needed because otherwise dividing two
quantities of the same dimension is ambiguous. You need it even if you
don't want the different return type (as I've given it).
--
Richard Smith
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]