Link to home
Start Free TrialLog in
Avatar of gysbert1
gysbert1

asked on

Overloading the -> operator

I am having trouble overloading the -> operator using C++ Builder 4 (not that I have got it going with any other compiler).

I need something like this.

class TPersonProxy
{
  private:
    char personName[256];

  public:
   // Compulsary constructor (no default provided)
    TPersonProxy(char *name)
   {
        strcpy(personName, name);
   };


    TPerson operator ->()
   {
      return getPersonClass(personName):
   }

  TPerson getPersonClass(char * Name);
};

class TPerson
{
    char Address[256];
}


main()
{
   TPersonProxy  Proxy("Johan Smith");

  printf("The Address for John Smith is %s\n", Proxy->Address);
}


This however generates a compiler error saying the -> operator must return a * or a class, even though I return a class!?
Avatar of Wyn
Wyn

operator–> is designed to be used when you want to make an object appear to be a pointer.
quote:
-> must be a member function. It has additional, atypical constraints: It must return either an object (or reference to an object) that also has a smart pointer or a pointer that can be used to select what the smart pointer arrow is pointing at.Example:

//: C12:Smartp.cpp
// Smart pointer example
#include <iostream>
#include <cstring>
using namespace std;

class Obj {
  static int i, j;
public:
  void f() { cout << i++ << endl; }
  void g() { cout << j++ << endl; }
};

// Static member definitions:
int Obj::i = 47;
int Obj::j = 11;

// Container:
class ObjContainer {
  enum { sz = 100 };
  Obj* a[sz];
  int index;
public:
  ObjContainer() {
    index = 0;
    memset(a, 0, sz * sizeof(Obj*));
  }
  void add(Obj* OBJ) {
    if(index >= sz) return;
    a[index++] = OBJ;
  }
  friend class Sp;
};

// Iterator:
class Sp {
  ObjContainer* oc;
  int index;
public:
  Sp(ObjContainer* objc) {
    index = 0;
    oc = objc;
  }
  // Return value indicates end of list:
  int operator++() { // Prefix
    if(index >= oc->sz) return 0;
    if(oc->a[++index] == 0) return 0;
    return 1;
  }
  int operator++(int) { // Postfix
    return operator++(); // Use prefix version
  }
  Obj* operator->() const {
    if(oc->a[index]) return oc->a[index];
    static Obj dummy;
    return &dummy;
  }
};

int main() {
  const int sz = 10;
  Obj o[sz];
  ObjContainer oc;
  for(int i = 0; i < sz; i++)
    oc.add(&o[i]); // Fill it up
  Sp sp(&oc); // Create an iterator
  do {
    sp->f(); // Smart pointer calls
    sp->g();
  } while(sp++);
} ///:~
class Pointer
{
public:
    Pointer(Foo * foo) : f(foo)
    {}
    Foo* operator->() const
    { return f; }
private:
    Foo* f;
};
....
Pointer p(new Foo);
p->MemberOfFoo();

----------------------------------

This works, using 'p' to indirectly invoke a member function of Foo.  The compiler treats any pointer to a struct or class, as a basic type (and there is a built-in operator-> for all basic types).  When the compiler sees a use of '->', it looks at the left-hand side; if it is a pointer-to-struct or pointer-to-class, the built-in operator-> is used to access a member.

However, if the left-hand side is a user-defined type, that type must overload operator->.  The overload must return either a pointer-to-struct or pointer-to-class, or some other user-defined type that also overloads operator->.  If the return value is a user-defined type, the compiler replaces the left-hand side with the return value from operator->, in this case a Foo*, and tries again until it ultimately comes up with a built-in pointer.

Thus, the following double indirection also works.

-------------------------------

class Pointer2
{
public:
    Pointer(Foo* foo) : p(foo)
    {}
    Pointer operator->() const
    { return p; }
private:
    Pointer p;
};
....
Pointer2 p(new Foo);
p->MemberOfFoo();

--------------------------------

Here, operator-> is evaluated three times:

1)  Pointer2::operator-> returns a Pointer
2)  Pointer::operator-> then returns a Foo*, and finally
3)  The compiler treats the Foo* as a basic type and accesses its member function.
O.K,in above,gysbert1,you can see the container wrap a pointer to array of objects pointers and use sp as a iterator to look through the pointers of objects contained in the containter and sp acts as a pointer .This way make the way acting with container more safe.
-> is ununually overloaded.
SO,you 'd better overload another operator.
Regards.
Wyn
Try,your answer is right but for   gysbert1's case,i strongly suggest not overload ->,that's the right crack gysbert should go rather than make a detour to overload ->.
 
Try,your answer is right but for   gysbert1's case,i strongly suggest not overload ->,that's the right crack gysbert should go rather than make a detour to overload ->.
 
Hi,
the problem is that operator -> should return pointer or class to which you can apply operator ->. This operator can be considered as unary operator, which means that when compiler encounters Proxy->Address it tries convert (Proxy->) to smth, and then to apply -> to the result.
Your operator returns TPerson and it is not possible to apply -> operator to TPerson.
All you have to do is to return pointer to a TPerson instead of TPerson itself.

Best regards,
Igor Proskuriakov
Here your return is a TPERSON , but sure your TPERSON class dont overload -> thus wrong.
like i mention in my first comment.
-> must be a member function. It has additional, atypical constraints: It must return either an object (or reference to an object) that also has a smart pointer(->) or a pointer that can be used to select what the smart pointer arrow is pointing at(This means the function or member behind -> is valid for the class pointed by your return pointer).


Hope helpful.
Wyn
While Wyn and Try are correct, I think they dwelt on the explanation of the language and missed pointing out the problem.  Proskig, correctly pointed out the problem and the solution.
Leave "gysbert1" to decide for himself what he wants to do.  I don't believe he needs anybody to strongly suggest, or otherwise, what he should or should not do.  He, himself stated that he has trouble overloading the '->' operator.  Let your comments, suggestions and solutions (etc.) be in response to what he's asking.

"gysbert1" is capable of making decisions for himself, as well as asking his own questions.
I don't want him to dwell on your long comments and answers, which while correct, may not be of dirrect help to him and miss the fact that his solution is explicitly stated in an innocent looking little comment that is likely to be missed.
Sometimes it's BETTER explaining to someone how he/she can solve their own problems as opposed to solving it for them.
Agreed,

feed a man and you give him a meal, teach him to cook and you feed him for life.

But sometimes, people need to see how all this stuff applies to them. Not everyone can relate abstract informatio, like you guys presented, to their concrete needs.  I just want to make sure gysbert1 gets both.
aha,just want to do some good but how this bad!
all is empty and void!
Best way is dodge
Who appointed you guardianship, "nietod"?
It must have been you.  I certainly didn't.
At no time did I say you were wrong, right?  All I said was that the specifc solution needed was explained by proskig.  How many times a week do we see problems where the client misses the answer they need because of the volume of information presented in the question?  I was just trying to avoid that.
"It must have been you."

----------------------------

You wish!!
No I don't.  I have never called myself a guardian or anything of the sort.  But you are.  Why?  I'm just trying to help people solve problems. I saw potential for a problem and tried to avoid it.  Instead you seem to have taken offense (At what I'm not sure, because I certainly didn't say anything against you) and cause a problem anyways.
You may not have called yourself a guardian, but every indication from your statements depicted you as having ascended that role.

I don't see anyplace where you have been appointed or delegated to speak on behalf of anyone.

Let people speak for themselves and/or ask their own questions.  Why do you feel you have to think and speak for them?
>> Indication from your statements depicted
>> you as having ascended that role
Because I contribute to a question?  That's crazy, that's what we are supposed to do.  

>> I don't see anyplace where you have
>> been appointed or delegated to speak
>> on behalf of anyone.
Well I can't argue with that.  But you just were???

>> Let people speak for themselves
Who am I speaking for?

>> Why do you feel you have to think
>> and speak for them?
You are telling me I think I am some sort of guardian.  You are telling me that I think I have a right to speak for others.  Which one of us is speaking for another?

I don't claim any special role or priviledge here.  I try to answer questions.  If I see mistakes or problems I try to point them out.  I don't do it to offend anyone.  I didn't say anything in this question that deserves this response.  I didn't say anything against you.  You were not wrong, and I even confirmed that.  But I pointed out that what he need to do was explained a simple little comment.  Why is that so bad?  Why does that mean I have a messiah complex?
Who said:

While Wyn and Try are correct, I think they dwelt on the explanation of the language and missed pointing out the problem.  Proskig, correctly pointed out the problem and the solution.

--------------------------------------

Are you some kind of umpire here?

--------------------------------------

Who said:

"I don't want him to dwell on your long comments and answers, which while correct, may not be of dirrect help to him and miss the fact that his solution is explicitly stated in an innocent looking little comment that is likely to be missed."

-----------------------------------

That is so replete with condescension, it's like "gysbert1" needs you to edit his capabilities for him, because he is so incapable of doing his own thinking and comprehesion for himself.

------------------------------------

Who said:

Not everyone can relate abstract informatio, like you guys presented, to their concrete needs.  I just want to make sure gysbert1 gets both.

------------------------------------

Right!!  Big daddy just want to make sure that little "gysbert1" gets taken care of properly, because little "gysbert1" cannot do it for himself.

-------------------------------------

Messiah complex?

WOW!!!  Condition is even worst than I thought it was!
Avatar of gysbert1

ASKER

I am not rejecting this because the answer is wrong but I will have to get technical here so please bear with me.

A simple pointer is most often a better response than lots of code. Code serves well to explain further though but as nietod pointed out the point is often lost in hundreds of lines of code that work somehow.

Try,
If you had any manners I would have just given you the points and left it there... Life is not about how many points you can get!

nietod,
3 years ago we "met" here and since I have had enormous respect for you and you deserve 100% to be the No.1. expert here. I agree that your response was appropriate and that Try over reacted in "protecting" his answer. Not many people have the passion to answer questions to such a degree that they will comment on answered questions.

I officially apoint nietod to act as guardian on any question that I might post in future !

In order not to give the points to Try I will get technical:
Wyn answered it correctly in a comment before it was locked by Try. I Quote "It has additional, atypical constraints: It must return either an object (or reference to an object) that also has a smart pointer or a pointer that can be used to select what the smart pointer arrow is pointing at."

Wyn, Please post an answer ...

Summary:

I simply did not realize that the returned class must implement the -> operator as well.

Clearly -> works so differently that it deserves its own section in the manuals. The error message (stated in the question) did not make sense until I read the comment from Wyn, as a matter of fact it only confused me (shame on Borland).

Thus:

If you overload -> you are not replacing the built in operator (as with most other operators), but you rather get a chance to do something before the built in operator is applied. The operator is effectively applied again after your overloaded operations are completed and this time on the result that you return.

In my case I had to return a class (on the stack) as I created the class with the factory function getPersonClass(...) and it would be destoyed as it left the scope of the operator if I only returned the pointer.

Simply adding
  TPerson * operator ->() {return this;};
to the TPerson class solved the problem.

I have however realized, shortly after posting the question, that this is a VERY VERY BAD implementation of a proxy. I had a look at the PROXY design pattern and now do it the right way, having an abstract base class define the interface and the real class and proxy class specialize that further as needed.
>> Try,
>> If you had any manners I would have just given
>> you the points and left it there... Life is not
>> about how many points you can get!
Although you can't tell from just one question, to Try's credit, he is not a "point-monger".

>> Clearly -> works so differently that it deserves
>> its own section in the manuals
Many C++ books do explain it well.  I believe it is in Stroustrup's "C++ Programming Language".  The technical term is that operator -> is "uncoupled" from its operand.  What this means is that after overloaded -> is applied to an operand, the operand is "removed" from the instruction stream and "replaced" by its result, but the -> still "remains" in the instruction stream of the statement (usually it would be removed) and is applied again.  This continues until the built-in -> is executed.  Note that this sounds' like it is being done at run-time, but it is all done at compile-time.
I have no quarrel with you "gysbert1", and I seek none.  You ask a question and I sought to answer it, ... CORRECTLY (even "nietod" agrees with that).

Yes, having spending many years in this profession, I do have a passion for it, and I cannot help if it shows.  I make no apology for that, and to be honest about it, I'm rather PROUD of it!  Nonetheless, one of the most gratifying thing I've gotten from this profession is the genuine exchange and interchange of ideas from a variety of sources, with NONE being so overbearing as to speak for the other.

I feel every input should be the genuine input of the source, ... and the source alone!!  Having said that, if from the onset you had expressed your preference for "nietod" to be the person to represent your ideas and will, I would have had no problem with that, and would have respected it.   However, in the absence of such expression, I view it as presumptuous for him to speak, think and choose for you, or anyone else when clearly he had no mandate for doing so.  "Let every source be the true representative of his/her own speech, ideas, and choice."  THAT, is the standard I was promoting.

This is not the first time I've clashed with "nietod", nor will it be the last.  It is part of his personality to be overbearing as though he speaks for all because he feels he has the patent to knowledge, and it will continue be my mantra to oppose that kind of arrogance.

I have no negative feelings about you rejecting my correct answer for whatever reason it be, since that is your choice to freely exercise, and I respect that.  Sadly, if your rejection was purely for punitive reasons, you also have that right to publicize what value you place on correct answers in patronage to other values.

Points have never been a primary concern for me here at EE, and your thoughts about not awarding me any, registers complete indifference to me.  You do not know this, but I've refused points from people many times in the past, as well as gotten upset with others for giving me points when I only submitted a comment to their questions and didn't want their points.

I started this comment by saying I have no quarrel with you, and I maintain that position that I seek none with you.
>> This is not the first time I've clashed with "nietod",
>> nor will it be the last.  It is part of his personality to
>> be overbearing as though he speaks for all because
>> he feels he has the patent to knowledge, and it will
>> continue be my mantra to oppose that kind of arrogance
It could be the last.  I have no desire for this.  

In a past question you said "I will take you on anyday, anytime nietod.  It is a pleasure".  Is it maybe possible that you are perhaps seeking these disputes?  No one else has complained to me.  You also had a bunch of these disputes with another top-top expert who then left EE because of it.  (Because of you personally, or at least you were the final straw, it was expressed to me in an e-mail)  He has since returned occassionally, due in part to my assurance that EE is improving.  
Are you speaking for someone else again "nietod"?
Who could I possibly be speaking for???
ASKER CERTIFIED SOLUTION
Avatar of Wyn
Wyn

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
You say you have no desire for this, but you MUST be enjoying it because you keep inviting me to respond.  You must be enjoying it.

I know the so-called 'top expert' to whom you're referring, and if I was the final straw, it was a straw he handed me.

He "answered" a question for which he was flat out, 100% wrong, and I pointed it out to him because the type hardware the questioner was asking about, were (and still are) the kind of machines I worked on everyday.  He obviously didn't like my crossing him and started the negatives.  Instead of being negative in return, I responded with sarcasm which infuriated him to the point that caused him to run to you.  I took the mud he slung at me and I didn't run to you, but as soon as he got a taste of his own medicine, he went crying to you.

I've never come crying to you about anything.  I take my lumps when they're dished out to me, but as soon as I return the favors, I become the trouble-maker.

Computer Science is what I studied in school.  Computer Science is what I worked in EVERYDAY.  I read, I study, I experiment, I work hard at my profession and I make no apology for the passion I have for it.  If someone thinks I'm too intense about it, perhaps that's why I'm successful at it, and perhaps it's why I can tell a 'top expert' he's wrong, ... when he's wrong.
>> You must be enjoying it.
Then am I just supposed to let you accuse me of this garbage?

>> He "answered" a question for which he was flat
>> out, 100% wrong
He was 100% correct and it took three other experts and a quote to convince you of it.  pehaps its a different case?  And it wasn't the fact that you were wrong that that made him leave, that happens, it was your attitude toward the other experts.

No one is infriging on your right to speak.  No one is saying you can't tell a top expert he's wrong.  That goes on all the time.  I make mistakes all the time.  Its pointed out all the time.  No big deal.  There isn't a single question where I've made a mistake and denied it.  (Last time this came up I went and dug up questions to prove this.  Why don't you dig up some counter examples?)  But here you aren't accusing me of making a mistake--which would be acceptible.  You're accusing me of acting as some sort of EE guestapo.  
I don't know what you mean by "gestapo"; that's an era unfamiliar to me.  I don't believe I can accuse you of something I am unfamiliar with.

Then I will admit, it must have been a different case indeed, and I am at a total lost why I wouldn't remember an incident that required three other experts and a quote to convince me I was wrong about something.  If I am contesting a technical issue, I have a whole library of books at my disposal, several high speed and powerful machines on which to run tests, and an impressive phalanx of technical people (many of whom are indisputably a lot smarter than I) to fall back on as resources.  These would be my references to whom I would resort for adjudication of a technical issue.  If in the end I did admit that I was wrong, it will have been because evidence of my incorrectness came from my side, and NOT from any expert at EE.

If I am wrong about something, I have no problem admitting to the whole world that I am wrong.  I view it as no shame when I am wrong to admit to it.  If anything, I believe it shows strength of my manhood to stand my ground and admit to it.  For this reason, the whole incident eludes me.
No denying that Wyn was first and correct here.

I agree with nietod that proskig provided the best explanation on the question, but Wyn posted the same answer (although not as clear) before him though.

I appreciate nietod pointing this out to me as his contibution could easily be overlooked. I am however convinced that the credit went to the correct person.

Try:
Clear your mind of the emotions and concentrate for a few seconds. Do yourself a favour and read nietod's comment and your response. If you are convinced that you acted fairly in posting "that garbage" you are an arogant fool and I pity you.

As for accusing people of speaking "for" other people you deserve the first prize! Read your comment  (the one that started this nonsense) where you explicitly and directly spoke "for" me (actually twice in one comment). No-one else in this discussion spoke "for" someone else as directly as that! I would be REALLY embarrassed if I was publically caught being THAT hypocritical and then making such a fuss over it.

I am, as you ironically enough pointed out, quite capable of doing just that. It seems to me, from the evidence, that you have no difficulty speaking for other people. This shows that you do not feel strong about the principle but actually rather enjoy picking fights with other experts over pityfull matters just for the heck of it.

Oh yes, almost forgot.

nietod,
This quote might stop you from loosing sleep over this issue ...

"Great spirits have always encountered violent opposition from mediocre minds." - Albert Einstein
Pfff, what a dispute. Was that neccesary Try? I can't see anything paternizing from nietod. And he dis say "I think"... I feel your reaction was rather strong.
Why don't you two take such issues to discuss in The Lounge?
It takes  a man, ... a REAL man, to walk away from a fight.  I'm going to walk away from this one, "gysbert1".

If you're going to quote Einstein, do him reverence and quote him in context.