Overloading operators in typedef structs (c++)

I want to make a typedef struct called pos (from position) that stores coordinates x and y. I am trying to overload some operators for this struct, but it does not compile.

typedef struct < int x; int y; inline pos operator=(pos a) < x=a.x; y=a.y; return a; >inline pos operator+(pos a) < return ; > inline bool operator==(pos a) < if (a.x==x && a.y== y) return true; else return false; >> pos; 
I also wanted to know the difference between this:
inline bool operator==(pos a)
bool operator==(pos a) const
69.6k 11 11 gold badges 105 105 silver badges 134 134 bronze badges asked Dec 26, 2012 at 22:44 3,692 2 2 gold badges 30 30 silver badges 51 51 bronze badges You might find this stack overflow article of interest. stackoverflow.com/questions/612328/… Commented Dec 26, 2012 at 22:48

You will likely want you pos a parameter regardless of operator to be a const pos& a (i.e. a const reference) rather than a pos copy. after you fix your declaration, of course.

Commented Dec 26, 2012 at 22:51

Once you solve your problems. You should also post on codereview to get comments on the rest of your code. There are some improvements you may want.

Commented Dec 26, 2012 at 22:53

4 Answers 4

The breakdown of your declaration and its members is somewhat littered:

Remove the typedef

The typedef is neither required, not desired for class/struct declarations in C++. Your members have no knowledge of the declaration of pos as-written, which is core to your current compilation failure.

typedef struct pos; 
struct pos < . >; 

Remove extraneous inlines

You're both declaring and defining your member operators within the class definition itself. The inline keyword is not needed so long as your implementations remain in their current location (the class definition)

Return references to *this where appropriate

This is related to an abundance of copy-constructions within your implementation that should not be done without a strong reason for doing so. It is related to the expression ideology of the following:

a = b = c; 

This assigns c to b , and the resulting value b is then assigned to a . This is not equivalent to the following code, contrary to what you may think:

a = c; b = c; 

Therefore, your assignment operator should be implemented as such:

pos& operator =(const pos& a)

Even here, this is not needed. The default copy-assignment operator will do the above for you free of charge (and code! woot!)

Note: there are times where the above should be avoided in favor of the copy/swap idiom. Though not needed for this specific case, it may look like this:

pos& operator=(pos a) // by-value param invokes class copy-ctor < this->swap(a); return *this; > 

Then a swap method is implemented:

void pos::swap(pos& obj) < // TODO: swap object guts with obj >

You do this to utilize the class copy-ctor to make a copy, then utilize exception-safe swapping to perform the exchange. The result is the incoming copy departs (and destroys) your object's old guts, while your object assumes ownership of there's. Read more the copy/swap idiom here, along with the pros and cons therein.

Pass objects by const reference when appropriate

All of your input parameters to all of your members are currently making copies of whatever is being passed at invoke. While it may be trivial for code like this, it can be very expensive for larger object types. An exampleis given here:

bool operator==(pos a) const

To this: (also simplified)

bool operator==(const pos& a) const

No copies of anything are made, resulting in more efficient code.

Finally, in answering your question, what is the difference between a member function or operator declared as const and one that is not?

A const member declares that invoking that member will not modifying the underlying object (mutable declarations not withstanding). Only const member functions can be invoked against const objects, or const references and pointers. For example, your operator +() does not modify your local object and thus should be declared as const . Your operator =() clearly modifies the local object, and therefore the operator should not be const .

Summary

struct pos < int x; int y; // default + parameterized constructor pos(int x=0, int y=0) : x(x), y(y) < >// assignment operator modifies object, therefore non-const pos& operator=(const pos& a) < x=a.x; y=a.y; return *this; >// addop. doesn't modify object. therefore const. pos operator+(const pos& a) const < return pos(a.x+x, a.y+y); >// equality comparison. doesn't modify object. therefore const. bool operator==(const pos& a) const < return (x == a.x && y == a.y); >>; 

EDIT OP wanted to see how an assignment operator chain works. The following demonstrates how this:

a = b = c; 

Is equivalent to this:

b = c; a = b; 

And that this does not always equate to this:

a = c; b = c; 

Sample code:

#include #include using namespace std; struct obj < std::string name; int value; obj(const std::string& name, int value) : name(name), value(value) < >obj& operator =(const obj& o) < cout >; int main(int argc, char *argv[]) < obj a("a", 1), b("b", 2), c("c", 3); a = b = c; cout 
)" data-controller="se-share-sheet" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f3.0%2f" data-se-share-sheet-license-name="CC BY-SA 3.0" data-s-popover-placement="bottom-start">Share
)">edited May 23, 2017 at 12:09
CommunityReplies to this bot are not monitored.">Bot
11 silver badge
answered Dec 26, 2012 at 23:24
8
    Ok, thanks. The only thing I don't understand is the part you say "This is not equivalent to the following code, contrary to what you may think", I keep thinking it is equivalent.
    – tuket
    CommentedDec 26, 2012 at 23:52
    @user1754322 It is one time that thinking of chained-assignments with parens helps understand what is going on (at least it helps me). a = (b = c); The b = c performs the assignment; the resulting value of that reduces to just b (after assignment), which is then assigned to a. I know, it can be confusing sometimes. You're not alone on that regard.
    – WhozCraig
    CommentedDec 26, 2012 at 23:57
    I think I understand it, but you said that a=b=c is not equivalent to: a = c; b = c; IMO it is.
    – tuket
    CommentedDec 27, 2012 at 0:02
    @user1754322 It is equivalent to b = c; a = b; I hope that makes sense. For trivial intrinsic types (int, etc. ) it may seem meaningless, but for complex types with custom assignment operators (yours) it is significant. If you desire I can update this answer with a very trivial example of how that assignment chain works.
    – WhozCraig
    CommentedDec 27, 2012 at 0:04
    2
    @user1754322 see (and try) the sample I posted at the end of this answer.
    – WhozCraig
    CommentedDec 27, 2012 at 0:17
|Show 3 more comments
7

Instead of typedef struct < . >pos; you should be doing struct pos < . >;. The issue here is that you are using the pos type name before it is defined. By moving the name to the top of the struct definition, you are able to use that name within the struct definition itself.

Further, the typedef struct < . >name; pattern is a C-ism, and doesn't have much place in C++.

To answer your question about inline, there is no difference in this case. When a method is defined within the struct/class definition, it is implicitly declared inline. When you explicitly specify inline, the compiler effectively ignores it because the method is already declared inline.

(inline methods will not trigger a linker error if the same method is defined in multiple object files; the linker will simply ignore all but one of them, assuming that they are all the same implementation. This is the only guaranteed change in behavior with inline methods. Nowadays, they do not affect the compiler's decision regarding whether or not to inline functions; they simply facilitate making the function implementation available in all translation units, which gives the compiler the option to inline the function, if it decides it would be beneficial to do so.)

)" data-controller="se-share-sheet" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f3.0%2f" data-se-share-sheet-license-name="CC BY-SA 3.0" data-s-popover-placement="bottom-start">Share
)">edited Dec 26, 2012 at 23:13
answered Dec 26, 2012 at 22:46
1
    2
    And if they are not all the same implementation, it's undefined behavior.
    – James Kanze
    CommentedDec 26, 2012 at 23:11
Add a comment|
5

try this:

struct Pos < int x; int y; inline Pos& operator=(const Pos& other)< x=other.x; y=other.y; return *this; >inline Pos operator+(const Pos& other) const < Pos res ; return res; > const inline bool operator==(const Pos& other) const < return (x==other.x and y == other.y); >>;