Question

I am having an issue with an assignment that I am working on. We are writing a complex number class that is defined within it's own namespace. I have everything working except the overloading on my istream and ostream. Let me post some of my code:

namespace maths {

    class complex_number{
    public:

        // lots of functions and two variables

        friend std::istream& operator >>(std::istream &in, maths::complex_number &input);

    }
}

std::istream& operator >>(std::istream &in, maths::complex_number &input)
{
   std::cout << "Please enter the real part of the number > ";
   in >> input.a;
   std::cout << "Please enter the imaginary part of the number > ";
   in >> input.b;

   return in;
}

int main(int argc, char **argv)
{
   maths::complex_number b;
   std::cin >> b;

   return 0;
}

The error that I am getting is the following:

com.cpp: In function ‘int main(int, char**)’:
com.cpp:159:16: error: ambiguous overload for ‘operator>>’ in ‘std::cin >> b’
com.cpp:159:16: note: candidates are:
com.cpp:131:15: note: std::istream& operator>>(std::istream&, maths::complex_number&)
com.cpp:37:26: note: std::istream& maths::operator>>(std::istream&, maths::complex_number&)

I've spent some time perusing the forum here and stumbled on an answer about name hiding but I can't seem to get it to work with my code. Any help is greatly appreciated!

Était-ce utile?

La solution

The reason it's ambiguous is because you have two separate functions. One resides in the maths namespace, and is declared by the one marked friend inside the class. This one can be found through Argument Dependent Lookup. You also have a full definition outside of the namespace. Both of these are equally valid.

To start, it's not accessing any private members of the class, so the friend declaration isn't needed. Simply don't make it a friend, as that just hurts encapsulation.

Secondly, I suggest moving the definition into the maths namespace because it belongs in there alongside the class it's operating on. As said before, ADL will still find it because the second argument is of a type in that namespace, so the namespace is searched and the overload found.

All in all, you should end up with this:

namespace maths {

    class complex_number{
    public:
        // lots of functions and two variables
    };

    std::istream& operator >>(std::istream &in, maths::complex_number &input)
    {
       std::cout << "Please enter the real part of the number > ";
       in >> input.a;
       std::cout << "Please enter the imaginary part of the number > ";
       in >> input.b;

       return in;
    }
}

int main(int argc, char **argv)
{
   maths::complex_number b;
   std::cin >> b; //operator>> found by ADL

   return 0;
}

One final note is the overload itself. Input really shouldn't prompt for inputs, it should just read them. This way, you can use it with the keyboard, a file, or whatever other derivative of std::istream is desired.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top