I am trying to overload an operator << in a class I created which compares two strings no matter the casing. Here is my bool operator
friend bool operator <<(const string& member, const string& player) {
return toLowerCase(member) == toLowerCase(player);
}
The program returns an error at this point in my code
current->name << member
Now current is a pointer to a node which contains a string name and member is a string that is passed by reference when the user is prompted. The error I get is
invalid operands to binary expression('string'(aka'basic_string<char>') and 'string')
The error message suggests it's not picking up your overload, but trying to use the built-in bitshift operator on strings (and failing, of course). I'm not sure why, given the information you've supplied.
Anyway, a much better idea would be to use a non-member, non-operator compare() function -- using operator<< to compare strings is just going to confuse the hell out of anybody looking at your code (even you, in a couple of years time).
Move that declaration out of your class and remove friend keyword:
bool operator <<(const string& member, const string& player)
{
return toLowerCase(member) == toLowerCase(player);
}
Live code.
Related
I have a Class called Request like this,
class Request {};
I store objects of this type in a global vector called,
std::vector<Request> requests;
I initialize the object using,
auto &request = requests.emplace_back();
Now, I attempt to delete the object using the reference provided by emplace_back like this,
requests.erase(std::remove(requests.begin(), requests.end(), request), requests.end());
It fails to compile and outputs following error,
sysroot/include/c++/v1\algorithm:2103:24: error: invalid operands to binary
expression ('Request' and 'const Request')
if (!(*__i == __value_))
~~~~ ^ ~~~~~~~~
What should I do here to make it compile?
In
requests.erase(std::remove(requests.begin(), requests.end(), request), requests.end());
The asker has been confused by answers to problems with std::erase and classes with no compiler-generated assignment operator. The problem here is not with std::erase and assignment operators, Request is, as presented at any rate, simple enough that the compiler will automatically generate an assignment operator for them. But keep an eye out for the Rule of Three and friends. Just because a default assignment operator can be generated doesn't mean the default behaviour is logically correct.
The asker's problem is with the std::remove portion of the line. std::remove needs a way to compare the Requests in requests to request to see which Requests match and need to be removed. std::remove uses the == operator to perform the comparison. The C++ compiler will not generate an equality operator for you because the odds of getting it wrong are far too high. For example, Which members are to be compared? All of them? One of them? First name and last name only? Student ID? Bank account number?
So we add a
bool operator==(const Request& lhs, const Request& rhs)
{
return /* comparison logic*/;
}
to do the heavy lifting.
See What are the basic rules and idioms for operator overloading? for further details and general wisdom about operator overloading.
The code compiles when defining operator==
class Request
{
public:
bool operator==(const Request &other) const {return true;}
};
Best regards.
I have a weird error when I try to compile this piece of code.
I will explain my problem.
I defined a vector2D as following:
typedef struct LX_Vector2D
{
float vx;
float vy;
LX_Vector2D& operator =(const LX_Vector2D v); // Defined
} LX_Vector2D;
I also defined two operators on this vector:
bool operator ==(LX_Vector2D& u,LX_Vector2D& v); // Are u and v equal?
LX_Vector2D operator -(LX_Vector2D& u); // Get the opposite vector
All of these overloaded operators was defined.
So I tested these operators in the following code:
LX_Vector2D u = {3.14,-2.56};
LX_Vector2D expected_vec = {-u.vx,-u.vy};
if(expected_vec == (-u)) // ERROR
cout << "OK" << endl;
else
cout << "NO" << endl;
When I compile this code, I have this error:
no match for ‘operator==’ in ‘expected_vec == operator-((* & u))‘
I have no problem with '=' and '==' because I defined and tested them before I implemented '-'.
But when I modify this code to get this:
u = -u;
if(expected_vec == u) // OK
I have no error.
I do not understand that, because it seems these two pieces of code are semantically identical.
Here is the definition of operator '-':
LX_Vector2D operator -(LX_Vector2D& u)
{
return {-u.vx,-u.vy};
}
So my question is:
Why doesn't my compiler recognize ‘expected_vec == (-u)‘ as a call of operator '==' with expected_vec and (-u) as parameters?
Another question:
How can I have the possibility to use if(expected_vec == (-u)) without any problem, if it is possible?
I use g++ 4.6.1.
The problem here is that the result from operator- when used as part of another expression is a temporary value, and that operator== takes non-constant references. A non-constant reference can't bind to a temporary value.
The simple solution? Make the operator== function take constant references:
bool operator ==(const LX_Vector2D& u, const LX_Vector2D& v)
// ^^^^^ ^^^^^
// Note the use of `const`
As a general recommendation, when declaring functions that will not modify their arguments, always pass the arguments as constant. It will avoid problems like this, and may also help the compiler with possible optimizations.
Operator - returns a temporary object:
LX_Vector2D operator -(LX_Vector2D& u)
while your comparison operator accepts a non-const reference:
bool operator ==(LX_Vector2D& u,LX_Vector2D& v)
Temporary objects, like returned by the - operator, cannot be used as non-const references. It's not allowed because there is no purpose modifying an object that is about to go out of scope anyway, so the compiler makes sure you don't even attempt it.
As a general rule, you should make any function that does not modify its arguments take const references instead, especially comparison functions:
bool operator ==(const LX_Vector2D& u,const LX_Vector2D& v)
in addition to the other answers, your assignment operator should also take a const& as in:
LX_Vector2D& operator =(const LX_Vector2D& v)
note the & after the parameter type.
As a general rule, and to avoid the construction of unnecessary copies of objects, parameters of complex types should almost always be const & if you are not planning on changing the parameter instance. Or if you are planning on changing the parameter instance, then simply as a reference, i.e., &.
I'm having some difficulty with this. I've determined I need to overload this operator for my personal project. It is necessitated by the use of the following line:
if(playerVec[i] == 0)
The player class has several data members for calculating one particular data member, mInitiative. This is the one I want to check in my if condition. Here is my attempt at overloading it:
bool operator==(const Player& lhs) const {
return mInitiative == lhs.mInitiative;
}
It seems fine enough, but the error persists. If I want to compare that particular player datum to an integer (in this case, 0), how do I go about it? What's the mistake in my approach?
EDIT: I have tried:
bool operator==(const Player& lhs, int rhs) const {
//...
}
But the compiler says there are too many parameters for the function. Why is this? Shouldn't == be able to take two?
Thanks!
There are two ways to overload an equality operator: declare it as a member, taking one argument (rhs); or declare it as a global, taking two arguments (lhs and rhs). Since your lhs is a Player, and your rhs is an integer, here are the two ways to define it:
// declared inside Player class as a member
bool operator == (int rhs) const
{
return mInitiative == rhs;
}
// can also be declared inside Player class, but is not a member due to friend keyword
friend bool operator == (Player const& lhs, int rhs)
{
return lhs.mInitiative == rhs;
}
That is leaving aside the style considerations of overloading operators in such a way.
When trying to overload equality operator (i.e. ==), you always need to think about whether the target instances are really the same.
In your case, I think people might be confused when reading the following code if you provide the Player to integer comparison. Since it looks like checking whether a pointer is null or not:
if(playerVec[i] == 0)
Rather than overloading == operator of Player to compare with integer, I would suggest providing a get() function, which allows you to compare Player with integer more clearly. For example:
if (playerVec[i].getPlayerID() == 0)
If you will use some stl function to manage your Player vector (eg. sorting), then you can overload == or > operator for two Player instances.
I'm writing my class now and testing it. It seems that the comma operator (operator,) refuses to work, the program simply skips it. This is the code I'm running
fileObj << buffer,40;
I wrote the following operators (only prototypes shown, the code isn't relevant):
const file_t& operator<<(const void* buffer);
void operator,(int length);
the "operator<<" works fine, the program uses it but when it arrives to the "operator," , it simply skips it like it doesn't even exist. Needless to say that both operators depend on each other.
Any idea why the comma operator is being skipped? Thanks.
Your << operator returns a const file_t reference. Your comma operator is a non-const function. Since the types don't match, the compiler does not select your comma operator to perform the operation. Instead, it uses the built-in comma operator, which simply evaluates both operands and returns the right one. (And since evaluation of the right operand has no side effects in your example, it appears as though it's not called at all.)
If your comma operator doesn't modify the object it's called on, then make it const:
void operator,(int length) const;
If the operator needs to modify your object, then don't return a const object from your << operator:
file_t& operator<<(void const* buffer);
I am currently reading information from an input file. Of that information, there is a name. All the information is read into a struct. There is an array of these structs.
I need to alphabetize the structs by the last name, using a Binary Search Tree.
Do I need to write an operator overload function for ==, <, and >. If so can someone help me get started on that?
Yes, you will want to write operator overloads for == and <. (> is not needed; just use the else case after checking e.g. if (a < b); else if (a == b).)
In our case, since we are alphabetizing by last name, one struct is "less than" another if and only if its last name comes before the other's last name alphabetically.
So what exactly is the problem? Do you know how to write operator overloads? Do you know how to compare strings and determine which comes first alphabetically?
You need a way to compare any two instances of the struct. Writing a comparison operator, say, operator<(), might be a convenient way to go about it.
class Record {
friend bool operator<(const Record&, const Record&);
std::string name;
// ...
};
bool operator<(const Record& a, const Record& b)
{
// return true if the name of a is less than the name of b
}
Because a node inserts either on the left subtree or the right subtree you only need to know if a node is "less than" another node. If it isn't, then it doesn't matter whether it's greater or equal to the other node; it goes on the other subtree either way.
Of course, you might need the equality comparison for some other task. If you do then it's a good idea to go all the way and provide the inequality operator as well.
Also of interest is the rel_ops namespace.
Operator overloads work just like functions or methods. They get a return type and arguments in just the same way. For instance, a binary operator (like <) would be a member function with one argument or a free function with two, one each for each side of the operator. the only thing that's different is instead of having an identifier function name, they use a special syntax, the keyword operator followed by the operator being overloaded. So if we wanted to have a comparable type, we could do it this way:
class MyUserType
{
private:
std::string sort_significant;
std::string sort_insignificant;
public:
bool operator<(const MyUserType &) const;
};
bool MyUserType::operator<(const MyUserType & other) const
{
return sort_significant < other.sort_significant;
}
You would normally need to overload <, but if there are other elements in the struct that you might sometime want to sort by, it doesn't really make sense to do that. You should write a separate function that accepts two parameters of your struct, and compares them by last name, returning true if the first should come before the second, false otherwise. Then pass that function to a std::sort. Something like this:
bool compare_by_last_name(const MyStruct & lhs, const MyStruct & rhs)
{
return lhs.last_name < rhs.last_name;
}
// later
vector<MyStruct> v;
// put some elements in v
std::sort(v.begin(), v.end(), compare_by_last_name);
You will notice I have ignored your statement "Using a binary search tree", because I don't quite know what you mean, but it's probably irrelevant. Did you make your own container class or something?