views:

79

answers:

2

As in the question, if I define a string operator in my class:

class Literal {
  operator string const () {
    return toStr ();
  };

  string toStr () const;
};

and then I use it:

Literal l1 ("fa-2bd2bc3e0");
cout << (string)l1 << " Declared" << endl;

with an explicit cast everything goes right, but if I remove the (string) the compiler says that it needs a cast operator declared in std::string. Shouldn't it cast my type automatically? SOLVED: I'm overloading operator<< (ostream& os, const Literal& l).

+8  A: 

No.. std::string would have to have a constructor that took Literal as an argument.

What you could do is overload operator << for your Literal class and have it cast and insert into the stream in there.

ostream &operator <<(std::ostream &stream, const Literal &rhs)
{
    stream << (string) rhs;
    return stream;
}
RC
If you are planning to use your class with the stream operations, you really should overload the << and >> operators. It makes using the class cleaner.
pstrjds
c++ has it's own set of conversion operators. Do not use c casts
VJo
A conversion constructor and conversion operator are equivalent when determining whether a function call is viable. The real reason the compiler won't do an implicit cast here is more complicated.
aschepler
Yeah, think I'll overload it...thanks
Glaedr
+5  A: 

Short answer: Keep using a cast or toStr(), or write your own operator<< function. (I would prefer l1.toStr() to (string)l1.)

Long answer: This might work if the Standard Library had a function

std::ostream& operator<<( std::ostream&, std::string const& );

Which it almost does, but not technically. Both ostream and string are really typedefs of template instantiations. And there's a template function for inserting one into the other.

// This is somewhat simplified.  For the real definitions, see the Standard
// and/or your complying implementation's headers.
namespace std {
  typedef basic_string<char> string;
  typedef basic_ostream<char> ostream;

  template <typename CharT>
  basic_ostream<CharT>& operator<<(
    basic_ostream<CharT>&, 
    basic_string<CharT> const&);
}

So when you use cout << str where the type of str is std::string, it can figure out to use that template function, with CharT = char.

But C++ doesn't allow you to have the compiler figure out both an implicit type conversion (Literal to string) and deduce template function template parameters (CharT = char) on the same call.

aschepler
Well said! Incidentally, this is why *operator const char \*(){}* **will** work whereas *operator string(){}* won't.
Mr.Ree