ofstream ambiguity problem

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • rince
    New Member
    • Jan 2008
    • 4

    ofstream ambiguity problem

    Hi! I have a complex class like

    Code:
    class Complex
    {
        double       re;
        double       im;
    
    public:
        Complex();
        Complex( const double &r, const double &i );
        Complex( const double &d );
        friend ofstream &operator<<( ofstream &stream, const Complex &c );
        [other stuff]
    };
    If I now write

    Code:
    ofstream ofs( "file.txt" );
    ofs << 1;
    this generates C2666 in MSVC - overloads have similar conversions. Looks like ofs << 1 requires an implicit conversion and the compiler is unsure whether to use basic_ostream<_ Elem,_Traits>:: operator <<(int) or to convert int to Complex and use operator <<(std::ofstrea m &,const Complex &).

    I could fix the problem in one of the following ways:
    1. Remove operator<< from Complex.
    2. Remove constructor Complex( const double &d ) from Complex.
    3. Write ofs.basic_ostre am<char, char_traits<cha r>>::operator<< ( 1 ) instead of ofs << 1.

    But nothing of the above seems acceptable. I can't believe things are really this screwed up, it doesn't seem like I'm doing anything wrong. Any suggestions?
  • weaknessforcats
    Recognized Expert Expert
    • Mar 2007
    • 9214

    #2
    Using Visual Sutdio.NET 2008 I get:

    error C2666: 'operator <<' : 17 overloads have similar conversions

    The real culprit here is the symbolic constant 1. You are no supposed to have constants like this in a position where the compiler has to play multiple choice.

    If this is truly an int (the default), then assign this value to an int and << the int.

    I would not typecast. I don't believe in it with C++ unless you are calling a relic C function. If you aren't then I believe your design is flawed.

    Comment

    • weaknessforcats
      Recognized Expert Expert
      • Mar 2007
      • 9214

      #3
      I got to thinking about your problem and thought that maybe if your friend was:
      [code=cpp]
      friend ostream &operator<<( ostream &stream, const Complex &c );
      [/code]

      it would help since an ofstream IS-A ostream. In fact, every inserter I have seen has used and ostream& argument.

      I tried this using your code and got a successful compile.

      Comment

      • rince
        New Member
        • Jan 2008
        • 4

        #4
        Oh, thanks, it really compiles ok with ostream. Still it's strange that it doesn't work with ofsream, why would there be any conversions? Such stuff really pisses me off.

        Comment

        • weaknessforcats
          Recognized Expert Expert
          • Mar 2007
          • 9214

          #5
          As long as you use defined types you will be OK. But if you use a symbolic constant you open yourself up to ambiguity.

          That 1, for example:

          Does the compiler:
          1) use it as an int with operator<<(ostr eam&, int&)?

          or,

          2) does it use it as a char with operator<<(ostr eam&, char&)?

          or,

          3) does it convert it to a double and use operator<<(ostr eam&, double&)?

          etc..
          etc...

          Don't give the compiler that latitude. If you have an int. Use an int variable.

          Comment

          Working...