C++ overloading operators

Yesterday I skimmed a large fraction of a C++ book. All through the book they use << for iostreams. As they say, operator overloading is syntactic sugar.

Anyway, last night it occurred to me that it would be interesting to try in LiquidCrystal to add that kind of syntax. But it seems to me that to be worthwhile, I'd also do something for setCursor.

So I thought I'd try to implement this syntactic sugar:
lcd<<"hello expresso machine";
lcd(8,3)<<"bye, now";

This would mean overloading << but tying it to print rather than iostreams
and overloading () and tying it to setCursor.

I thought << would both want to return 'this' so that you could write:
lcd(0,0)<<"upper left"<<" "<<x;
I pared that away as I was trying to get it to compile and changed the type of the fcn to void.

I realize that I will need several overloaded versions of <<, mimicking what is in 'print', but for now one seemed like a place to start. So I have

void LiquidCrystal::operator<< (const char str[]) {  //there are a half dozen overloaded versions of print
  LiquidCrystal::print(str);
//  return this;
  }
  
//void LiquidCrystal:operator() (uint8_t col,uint8_t row) {
void LiquidCrystal:operator() (uint8_t col,uint8_t row)  {
  setCursor(0,row);
//  return this;
  }

and the only error left when I compile refers to operator():

/Applications/Arduino.app/Contents/Resources/Java/libraries/LiquidCrystal/LiquidCrystal.cpp:337: error: function definition does not declare parameters

I tried reducing it to one argument (ie just the row) and the message didn't change. I've had little luck trying to google up info on overloading () and the book I have barely mentions that operator. The one instance of overloading () I found looks pretty similar to what I have. It is at:
http://www.parashift.com/c++-faq-lite/operator-overloading.html

the error msg says definition not declaration, but for completeness the .h file has this:

      void operator() (uint8_t, uint8_t);
      void operator<<      (const char*);

With

LiquidCrystal* operator() (uint8_t, uint8_t) const;
LiquidCrystal* operator<<      (const char*);

and this

LiquidCrystal* LiquidCrystal::operator<< (const char str[]) {  //there are a half dozen overloaded versions of print
  LiquidCrystal::print(str);
  return this;
  }

LiquidCrystal* LiquidCrystal:operator() (uint8_t col,uint8_t row) const {
  setCursor(col,row);
  return this;
  }

I've got the return type compiling but still no clue about this missing parameter thing.

: instead of ::
doh!
haven't tried it but it will work.

Typically, overloading the << for an iostream class requires that the function return an iostream reference (rather than a pointer), so that:

cout << "This is " << " some output" << endl;

behave correctly for all << occurrences.

Thanks, I'm seeing that now. I don't think iostream is available or economical; I was hoping that if I returned the LiquidCrystal object it would let me string them together. so far I can get it to understand what I mean when I say LiquidCrystal* LiquidCrystal::operator<<,
but when I take the * out I think it loses my drift. I think I'll keep playing with it and see how it goes.

Replace the * with a &.

Here's where I ended up

in the .h

LiquidCrystal& operator() (uint8_t, uint8_t) ;
LiquidCrystal& operator<<      (const char*);

and in .cpp

LiquidCrystal& LiquidCrystal::operator<< (const char str[]) {  //there are a half dozen overloaded versions of print
  LiquidCrystal::print(str);
  return *this;
  }

LiquidCrystal& LiquidCrystal::operator() (uint8_t col,uint8_t row)  {
  setCursor(col,row);
  return *this;
  }

This works:

    lcd(0,1);
    lcd<<"streamish output";
    lcd(8,2)<<"ab";
    lcd(2,2)<<"cd";
    lcd(0,2)<<"12";

but you can't chain beyond the first character string.

I haven't tried to implement the various versions of << that would be needed for full functionality: int, long, char etc.

This DOES work, however:

    char  a[80]="ab";
    lcd(8,2)<<a<<"cd";

I have 2 questions:
In print, why is Print::printFloat a PRIVATE method?

Does anyone understand why I can write lcd(2,0)<<a<<"text string" but not lcd(0,0)<<"text1"<<"text2" ?

it seems like it must have something to do with the constant string bollixing up the return type so that the expression evaluator doesn't think there is a LiquidCrystal object on the left side of the second << in the second case, but does think that in the first case.

Did you see this thread:

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1231224786/all

with respect to the send question, when I put this in the .cpp file:

LiquidCrystal& LiquidCrystal::operator<< (const char str[]) {  //there are a half dozen overloaded versions of print
  LiquidCrystal::print(str);
  return *this;
  }
 LiquidCrystal& LiquidCrystal::operator<<      (char c) {
   LiquidCrystal::print(c,10);
   return *this;
  }
 LiquidCrystal& LiquidCrystal::operator<<      (unsigned char c) {
   LiquidCrystal::print(c,10);
   return *this;
  }
 LiquidCrystal& LiquidCrystal::operator<<      (int c) {
   LiquidCrystal::print(c,10);
   return *this;
  }
 LiquidCrystal& LiquidCrystal::operator<<      (unsigned int c) {
   LiquidCrystal::print(c,10);
   return *this;
  }
 LiquidCrystal& LiquidCrystal::operator<<      (long c) {
   LiquidCrystal::print(c,10);
   return *this;
  }
 LiquidCrystal& LiquidCrystal::operator<<      (unsigned long c) {
   LiquidCrystal::print(c,10);
   return *this;
  }

LiquidCrystal& LiquidCrystal::operator() (uint8_t col,uint8_t row)  {
  setCursor(col,row);
  return *this;
  }

I can write this:
lcd(0,2)<<12<<' '<<5000;
so a one character ' ' works OK but "ab" doesn't

Westfw
Many thanks!!! that is a much better implementation than what I was playing with. very neat.

adding just one line to LiquidCrystal.h:      inline LiquidCrystal& operator() (uint8_t x, uint8_t y) {setCursor(x,y); return *this;}

and including Streaming.h in your pde file gives exactly what I was hoping for. Plus, Streaming.h is so efficient it will likely save a few bytes of flash! Very neat.