grzkv
grzkv

Reputation: 2619

Change the complex number output format

There is the complex<> template in C++ standard library, and it has an overloaded << operator so that it outputs complex numbers in the (real_part, im_part) format. I need to change the behavior of that operator for complex numbers so that the output format is changed to something completely different. Specifically, I need the output to be in the form real_part\tim_part. How do I do that?

Upvotes: 6

Views: 2844

Answers (5)

tesch1
tesch1

Reputation: 2806

My answer to the same question here: c++ display complex number with i in imaginary part produces the behavior you want, at the expense of some risk of future incompatibility because it inserts a template specialization into the std:: namespace.

Upvotes: 0

Edward Strange
Edward Strange

Reputation: 40859

For any specific instantiation of complex<T>, Use a strong typedef (boost has a version) and cast to that type during << calls. Override << for that type.

If you need to override << for any variation of complex<T> then life will be harder.

Upvotes: 1

Johan Kotlinski
Johan Kotlinski

Reputation: 25739

There is no really tidy way to do that. My suggestion would be to just ditch iostreams and write something more C-like instead. It will probably be faster to write, faster to read and faster to execute.

Upvotes: -1

Fred Nurk
Fred Nurk

Reputation: 14212

template<class T>
struct my_complex_format_type {
  std::complex<T> const &x;
  my_complex_format_type(std::complex<T> const &x) : x (x) {}
  friend std::ostream& operator<<(std::ostream &out,
                                  my_complex_format_type const &value)
  {
    out << "format value.x however you like";
    return out;
  }
};
template<class T>
my_complex_format_type<T> my_complex_format(std::complex<T> const &x) {
  return x;
}

void example() {
  std::cout << my_complex_format(some_complex);
}

Upvotes: 3

templatetypedef
templatetypedef

Reputation: 372784

There's no direct way to replace operator <<, but you do have a few options. First, you could just write your own function to print complex numbers:

template <typename T> void PrintComplex(const complex<T>& c) {
    /* ... */
}

If you want to still use the nice stream syntax, then one trick you could do would be to make a wrapper class that wraps a complex and then defines its own operator << that prints it out in a different way. For example:

template <typename T> class ComplexPrinter {
public:
    /* Conversion constructor allows for implicit conversions from
     * complex<T> to ComplexPrinter<T>.
     */
    ComplexPrinter(const complex<T>& value) : c(value) {
        // Handled in initializer list
    }

    /* Output the complex in your own format. */
    friend ostream& operator<< (ostream& out, const ComplexPrinter& cp) {
        /* ... print in your own format ... */
    }

private:
    complex<T> c;
};

Once you have this, you could write something like

cout << ComplexPrinter<double>(myComplex) << endl;

You can make this even cleaner by writing a function like this one to wrap the object for you:

template <typename T>
ComplexPrinter<T> wrap(const complex<T>& c) {
    return ComplexPrinter<T>(c);
}

This then lets you write

cout << wrap(myComplex) << endl;

Which isn't perfect, but is pretty good.

One thing to note about the above wrapper is that it has an implicit conversion constructor set up to let you convert complex<T>s to ComplexPrinter<T>s. This means that if you have a vector< complex<T> >, you can print it out using your custom code by calling

vector< complex<double> > v = /* ... */
copy (v.begin(), v.end(), ostream_iterator< ComplexPrinter<double> >(cout, " "));

On output, the implicit conversion constructor will transform your complex<double>s into the wrappers, and your custom code will do the printing for you.

If you want to be very adventurous and cast caution to the wind, you could even write the class so that it just stores a reference to the original complex, as shown here:

template <typename T> class ComplexPrinter {
public:
    /* Conversion constructor allows for implicit conversions from
     * complex<T> to ComplexPrinter<T>.
     */
    ComplexPrinter(const complex<T>& value) : c(value) {
        // Handled in initializer list
    }

    /* Output the complex in your own format. */
    friend ostream& operator<< (ostream& out, const ComplexPrinter& cp) {
        /* ... print in your own format ... */
    }

private:
    const complex<T>& c;
};

This completely eliminates any copying and just makes the wrapper a thin veneer around a real complex. (No pun intended). You'd have to be very careful if you did this not to pass these objects around across scope boundaries where the original objects go out of scope, but if it's what you want it might work out just great.

Hope this helps!

Upvotes: 7

Related Questions