Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Implicit conversion to complex<double>

Reply
Thread Tools

Implicit conversion to complex<double>

 
 
perroe@nr.no
Guest
Posts: n/a
 
      07-12-2007
Hi

I have a array of complex numbers that are stored in a simple double
array. This is done since the array is part of an wrapper for an
external C library, and the imaginary part of the first element, and
the last element are known to be 0. I've implemented a []-operator
that returns a ComplexReference object that basically maps a
complex<double> into the storage used in the array.

What I would like to do is using the ComplexReference object as a
complex<double> object, as shown in the code below, but I can not do
this implicitly, only through the explicit cast.

Is there any way to make this work so that the ComplexReference object
will behave like a complex<double> from the users point of view
without wrapping all the functions associated with std::complex, using
a temporary complex<double> object, or using a explicit cast?

#include "complexarray.h"

#include <complex>
#include <iostream>

int main()
{
ComplexArray a(6);

// Works:
a[0] = std::complex<double>(1.0, 0.0);
a[1] = std::complex<double>(5.1, 2.0);
a[2] = std::complex<double>(2.0, 1.1);
a[3] = std::complex<double>(5.5, 0.0);

// Does not work:
std::cout << "|a[2]| = " << std::abs(a[2]) << "\n";

// Works
std::cout << "|a[2]| = " <<
std::abs(static_cast<std::complex<double> >(a[2])) << "\n";

// Also works
std::complex<double> c = a[2];
std::cout << "|a[2]| = " << std::abs(c) << "\n";

exit(EXIT_SUCCESS);
}


complexarray.h:

#include <complex>
#include <vector>

class ComplexReference {
public:
ComplexReference(double& re, double& im)
: re_(re), im_(im) {}

inline operator std::complex<double>() const
{
return std::complex<double>(re_, im_);
}

inline ComplexReference&
operator=(const std::complex<double> c)
{
re_ = c.real();
im_ = c.imag();
return *this;
}

private:
double& re_;
double& im_;
};

class ComplexArray {
public:
typedef ComplexReference reference;
typedef std::complex<double> const_reference;

// Note: n is length of data, not number of complex elements.
explicit ComplexArray(int n = 0) : data_(n), dummy(0) {}

inline const_reference operator[](size_t i) const
{
size_t n = data_.size();
if (i == 0 || (i == n/2 && n%2 == 0)) {
return const_reference(data_[i], 0);
}
return const_reference(data_[i], data_[data_.size() - i]);
}

inline reference operator[](size_t i)
{
size_t n = data_.size();
if (i == 0 || (i == n/2 && n%2 == 0)) {
return reference(data_[i], dummy);
}
return reference(data_[i], data_[data_.size() - i]);
}

inline size_t size() const
{
return data_.size() / 2 + 1;
}

private:
/// The data vector.
std::vector<double> data_;

/// Dummy object.
double dummy;
};

--
Per Rĝe

 
Reply With Quote
 
 
 
 
Robert Bauck Hamar
Guest
Posts: n/a
 
      07-12-2007
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:

> Hi
>
> I have a array of complex numbers that are stored in a simple double
> array. This is done since the array is part of an wrapper for an
> external C library, and the imaginary part of the first element, and
> the last element are known to be 0. I've implemented a []-operator
> that returns a ComplexReference object that basically maps a
> complex<double> into the storage used in the array.
>
> What I would like to do is using the ComplexReference object as a
> complex<double> object, as shown in the code below, but I can not do
> this implicitly, only through the explicit cast.
>
> Is there any way to make this work so that the ComplexReference object
> will behave like a complex<double> from the users point of view
> without wrapping all the functions associated with std::complex, using
> a temporary complex<double> object, or using a explicit cast?


Not really. One class can never behave just like another. For example, only
one user defined conversion may be called implicitly to match a function
argument. The problem with the functions associated with std::complex are
that they are templates. If you take std::abs, you have

double abs(double);
float abs(float);

and so on in <cmath>,
and the function you are interested in, is

template <class T> T abs(const complex<T>&);

And as you have seen, the compiler will not even try this. The problem is
that T cannot be deduced.

> #include "complexarray.h"
>
> #include <complex>
> #include <iostream>
>
> int main()
> {
> ComplexArray a(6);
>
> // Works:
> a[0] = std::complex<double>(1.0, 0.0);
> a[1] = std::complex<double>(5.1, 2.0);
> a[2] = std::complex<double>(2.0, 1.1);
> a[3] = std::complex<double>(5.5, 0.0);
>
> // Does not work:
> std::cout << "|a[2]| = " << std::abs(a[2]) << "\n";
>
> // Works
> std::cout << "|a[2]| = " <<
> std::abs(static_cast<std::complex<double> >(a[2])) << "\n";


This works because both the argument for abs and its expected parameter is
on the form
std::complex<T>,
which means T can be deduced.

>
> // Also works
> std::complex<double> c = a[2];
> std::cout << "|a[2]| = " << std::abs(c) << "\n";


//Also works:
std::cout << std::abs<double>(c);

Here, there are only one candidate, and the template parameter is selected
by hand.

//Also works
std::cout << abs(std::complex<double>(c));

This is the cast with function style syntax. At least it is shorter than
static_cast. Note that since the argument is a class from std, the compiler
will look for abs in std.

>
> exit(EXIT_SUCCESS);


EXIT_SUCCESS is declared in <cstdlib>/<stdlib.h>

> }
>
>
> complexarray.h:
>
> #include <complex>
> #include <vector>
>
> class ComplexReference {
> public:
> ComplexReference(double& re, double& im)
> : re_(re), im_(im) {}
>
> inline operator std::complex<double>() const


Note that inline is implied for functions defined inside the class
definition.

> {
> return std::complex<double>(re_, im_);
> }
>
> inline ComplexReference&
> operator=(const std::complex<double> c)
> {
> re_ = c.real();
> im_ = c.imag();
> return *this;
> }
>
> private:
> double& re_;
> double& im_;
> };
>
> class ComplexArray {
> public:
> typedef ComplexReference reference;
> typedef std::complex<double> const_reference;
>
> // Note: n is length of data, not number of complex elements.
> explicit ComplexArray(int n = 0) : data_(n), dummy(0) {}
>
> inline const_reference operator[](size_t i) const


size_t should be a typedef. It is defined in <cstddef>, <cstdio>, <cstring>
and <ctime>, and unless you include one of the .h variants, you should use
std::size_t, or write using std::size_t. Here, however, the correct type
would be std::vector<double>::size_type.

> {
> size_t n = data_.size();
> if (i == 0 || (i == n/2 && n%2 == 0)) {
> return const_reference(data_[i], 0);
> }
> return const_reference(data_[i], data_[data_.size() - i]);
> }
>
> inline reference operator[](size_t i)
> {
> size_t n = data_.size();
> if (i == 0 || (i == n/2 && n%2 == 0)) {
> return reference(data_[i], dummy);
> }
> return reference(data_[i], data_[data_.size() - i]);
> }
>
> inline size_t size() const
> {
> return data_.size() / 2 + 1;
> }
>
> private:
> /// The data vector.
> std::vector<double> data_;
>
> /// Dummy object.
> double dummy;
> };


--
rbh
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Problem with implicit conversion Boris C++ 3 08-26-2004 02:03 PM
Implicit/explicit conversion al C++ 2 01-07-2004 10:18 AM
Implicit conversion is evil? Russell Reagan C++ 2 10-27-2003 04:44 PM
Question on additional decimals in implicit conversion Jacob Java 7 10-03-2003 10:23 PM
implicit vs. explicit type conversion for string vs. (char *) dmoos AT esigma-systems DOT de C++ 2 06-26-2003 04:32 PM



Advertisments