ISO C++ says that these are ambiguous,
Asked Answered
B

2

5

I have to overload the shift operator " << " both for writing in console and to write on a binary file..

I am doing okay for the ostream overloading, while I am having some problem overloading the fstream, here it is:

in my header:

friend ostream &operator<<(ostream &, const Fotografia &);
friend fstream &operator<<(fstream &, const Fotografia &);

in my cpp file:

fstream &operator<<(fstream & miofile, const Fotografia & sorgente)
{
        //Open the file
        miofile.open("data.dat", ios::binary | ios::app);
        if(!miofile) cerr << "Can't open the file\n";
        miofile << strlen(sorgente.Titolo);
        miofile << endl;        
        miofile << sorgente.Titolo;
        //I close the file
        miofile.close();
        return miofile;

}

Here's the error I am facing:

In function `std::fstream& operator<<(std::fstream&, const Fotografia&)':

ISO C++ says that these are ambiguous, even though the worst conversion for the first is    better than the worst conversion for the second:

std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, const char*) [with _Traits = std::char_traits<char>] 

std::fstream& operator<<(std::fstream&, const Fotografia&) 

What I understood so far is that there's ambiguosity between the overloaded function I just created and the standard fstream << . Now, what I do not understand is why, because my overloaded function should work just for the class "Fotografia" (which was created by me), while I am trying to write a char * .

I thought I could solve this problem by calling the fstream operator with the "::" scope but I am not sure.

Could anyone help me out here please? :)

EDIT:

I am posting the code for the header and the code for the constructor

         //Costruttore,distruttore,costruttore di copia,operatore di assegnazione.
         Fotografia(char * titolo = "Untitled" , char * formato = ".jpeg");
         ~Fotografia() { delete [] Titolo; delete [] Formato;}
         Fotografia(const Fotografia &);
         Fotografia &operator=(const Fotografia &);

This is in the cpp:

 Fotografia::Fotografia(char * titolo , char * formato)
 {
     Titolo = new char[strlen(titolo)+1];
     strcpy(Titolo,titolo);
     Formato = new char[strlen(formato)+1];
     strcpy(Formato,formato);
  } //Fine costruttore
Beau answered 30/1, 2013 at 18:3 Comment(2)
An fstream is an ostream.Muscovite
Shouldn't the fstream passed into operator<< be opened and closed by the caller? as it is passing it in and out of the function is kind of pointless. About your problem: Do you have any implicit conversions between char* and Fotografia (operator char* or Fotografia(const char*))?Trichinosis
B
4

Get rid of the operator char* in Fotografia, or mark it explicit.

Also, instead of limiting the code to inserting in an fstream, you could insert into an arbitrary basic_ostream. That would still work for an fstream, and would give you more flexibility to use other forms of output streams. That would also eliminate the error.

Bastogne answered 30/1, 2013 at 18:8 Comment(5)
I'm not sure I'm following you, Pete. Both fstream and ostream are ultimately basic_ostream<char>. He could try using basic_ostream<unsigned char>, but I'm not sure the behavior is defined if he does. The standard doesn't specify any semantics for it, and I suspect that something like std::basic_ofstream<unsigned char> will not work in most implementations. (Personally, I still think making the iostreams templates, rather than just supplying two separate classes, was a mistake. Sort of violates the KISS principle, since you can only use two instantiations anyway.)Miskolc
@JamesKanze: Wouldn't having different classes for char and wchar_t violate DRY? Especialy when it comes to supporting custom streamout for both cases. Always writing a completely generic template and using sfinae to enable it only for stream classes is a bit cumbersome afterall.Trichinosis
@JamesKanze - heh, I didn't read the question carefully enough. Still, I stand by the conclusions, even if the logic is flawed. <g>Bastogne
@Trichinosis I'm not sure what DRY means, but... One of the problems with the template solution is that it forces both classes to have the same semantics. When they really shouldn't.Miskolc
I made an edit to my first post and put the code for my header and constructor, I don't have the "operator char*" anywhere, could you please point out what I should mark explicit? Thanks a lot for your patience and kind help! ---Edit: Got it! Thanks for your help!!! ---Beau
M
3

It makes no sense to overload operator<< for std::fstream. First, because experienced C++ programmers hardly every use std::fstream; they use std::ofstream or std::ifstream. And second, because once you've used a <<, the return value is a std::ostream anyway, so the operator<< for ofstream would never be called.

Of course, your implementation of the operator also violates all of the rules. You don't open or close a file in the operator; the operator is for formatting the data. If you want to support two different formats, the usual way would be to define a manipulator to choose between them, and let the client decide. (See std::ios_base::xalloc() and company for where to put the additional state.)

Miskolc answered 30/1, 2013 at 18:23 Comment(1)
Good point, I'll try and use accordingly ofstream and ifstream instead of fstream. Also, I am going to let the user open and close the file, while the operator manipulates the data. Thanks for your help!Beau

© 2022 - 2024 — McMap. All rights reserved.