I'm porting a class which implements IEquatable<T> and IComparable<T> and overrides ==, !=, < and > from C# into C++/CLI. So far I have:
Header:
virtual bool Equals(Thing other);
virtual int CompareTo(Thing other);
static bool operator == (Thing tc1, Thing tc2);
static bool operator != (Thing tc1, Thing tc2);
static bool operator > (Thing tc1, Thing tc2);
static bool operator < (Thing tc1, Thing tc2);
Source file:
bool Thing ::Equals(Thing other)
{
// tests equality here
}
int Thing ::CompareTo(Thing other)
{
if (this > other) // Error here
return 1;
else if (this < other)
return -1;
else
return 0;
}
bool Thing ::operator == (Thing t1, Thing t2)
{
return tc1.Equals(tc2);
}
bool Thing ::operator != (Thing t1, Thing t2)
{
return !tc1.Equals(tc2);
}
bool Thing::operator > (Thing t1, Thing t2)
{
// test for greater than
}
bool Thing::operator < (Thing t1, Thing t2)
{
// test for less than
}
I'm not sure why the original tested equality in the interface and compared things in the operator, but I'm trying to preserve the original structure.
Anyway, I get a compilation error at the marked line: "error C2679: binary '>' : no operator found which takes a right-hand operand of type 'ThingNamespace::Thing' (or there is no acceptable conversion)", and a corresponding error two lines below. Why isn't it picking up the existence of the overloaded operator?
this is a pointer, you'll need to dereference it.
if ((*this) > other)
return 1;
else if ((*this) < other)
return -1;
else
return 0;
return (*this) == other ? 0 : ((*this) > other ? 1 : -1);
as arul said, you need to dereference the this keyword, but on a side note, you should probably use const references in your function paramaters instead of passing the object since:
-C++ passes all objects by value, not by reference(which is what happens in C#), so using references reduces the overhead.
-It'll let you use functions from the standard library such as std::sort without needing to explicitly specify a new comparison operator
Related
I've read somewhere that a variable should be entered into the code if it is reused. But when I write my code for logic transparency, I sometimes create intermediate variables (with names reflecting what they contain) which are used only once.
How incorrect is this concept?
PS:
I want to do it right.
It is important to note that most of the time clarity takes precedence over re-usability or brevity. This is one of the basic principles of clean code. Most modern compilers optimize code anyway so creating new variables need not be a concern at all.
It is perfectly fine to create a new variable if it would add clarity to your code. Make sure to give it a meaningful name. Consider the following function:
public static boolean isLeapYear(final int yyyy) {
if ((yyyy % 4) != 0) {
return false;
}
else if ((yyyy % 400) == 0) {
return true;
}
else if ((yyyy % 100) == 0) {
return false;
}
else {
return true;
}
}
Even though the boolean expressions are used only once, they may confuse the reader of the code. We can rewrite it as follows
public static boolean isLeapYear(int year) {
boolean fourth = year % 4 == 0;
boolean hundredth = year % 100 == 0;
boolean fourHundredth = year % 400 == 0;
return fourth && (!hundredth || fourHundredth);
}
These boolean variables add much more clarity to the code.
This example is from the Clean Code book by Robert C. Martin.
Consider a class with id field which might be null until stored in database:
class IdableK<T : IdableK<T>> : Comparable<T> {
private var id : Long? = null
}
I am trying to implement a compareTo method as follows:
override fun compareTo(other: T): Int {
if (id == null) {
return -1;
}
if (other.id == null) {
return 1;
}
return id!!.compareTo(other.id!!)
}
Is this a correct way of doing it? Would there be a simple way of doing it?
Check out the kotlin.comparisons package. e.g. You can use compareValues:
class IdableK<T : IdableK<T>> : Comparable<T> {
private var id: Long? = null
override fun compareTo(other: T) = compareValues(id, other.id)
}
This is incorrect. If you have two instances with their ids set to null, both instances will return -1 when you call compareTo(other) on them, while if one returns -1 the other should return 1 in a correct implementation. I'm not sure if there are situations where it makes sense to implement compareTo based on nullable properties, but I can't imagine any. Maybe there's a better way for you too?
Also, you should avoid non-null assertions (!!). Since you're using vars, other threads may change the value to null so that even if you did a null check before, the value is now null and !! throws. Instead, you should store both ids in local variables and check these for null values.
If you absolutely have to use compareTo, I'd do it like this:
override fun compareTo(other: T): Int {
val thisId = id
val otherId = other.id
if (thisId == null && otherId == null) return 0
if (thisId == null && otherId != null) return -1
if (thisId != null && otherId == null) return 1
// thisId and otherId are now smart cast to Long
return thisId.compareTo(otherId)
}
Here is a simple way:
override fun compareTo(other: T) :Int {
return id?.compareTo(other.id ?: return 1) ?: -1
}
However this piece of code is very unfriendly to a novice kotlin programmer. It involves too much magic that make it look like scala. These 3 question marks make people puzzled, at least they must think for a minute or two before they could realize what is going on in this minimalistic one-liner. I still prefer your edition. It's more verbose, but clear.
And I'm really worried about the symmetric problem. This matters, and isn't just a design problem. If you don't compare nullable properties, there won't be this programming puzzle. It will just be override fun compareTo(other: T) = id.compareTo(other.id). Simple, clear, and no misleading.
I would rather throw away all null checking code and just live with those null assertions. Because mostly you won't compare there things until it is fully initialized. If these assertion fails, it means something really bad has happens.
Oh, BTW, I don't know about your project, and if it hits the rare cases that you have to compare nullable properties, I think you could write a special edition of Comparator that consider nulls instead of throwing NPEs. Don't mess with the natural order.
While reading some refactoring practices I stumbled upon this article
The author arguments to modify below code with getter and setters, I think they should be private but anyways what's the benefit in doing so? aren't we introducing the function call overhead?
Before:
private int _low, _high;
boolean includes (int arg) {
return arg >= _low && arg <= _high;
}
After:
private int _low, _high;
boolean includes (int arg) {
return arg >= getLow() && arg <= getHigh();
}
int getLow() {return _low;}
int getHigh() {return _high;}
Let's say, for some reason you need to change the names of your class attributes from _low, _high to _min, _max. In the 1st version, you need to modify the includes() function as well. In the 2nd version you only need to modify the getters. In your example the benefit is small, but in a bigger class it could save you a lot of work.
A slightly more complex example where the upper value is no longer stored but derived from the lower value and an interval:
private int _low, _interval;
boolean includes (int arg) {
return arg >= getLow() && arg <= getHigh();
}
int getLow() {return _low;}
int getHigh() {return _low + _interval;}
Again you only need to modify the getter.
Concerning the overhead: Depending on the language you are using, your compiler will optimize the function call away.
In my instance method, would like to compare a BOOL parameter with the content of a static variable, for instance:
- (NSArray*)myMethod:(NSString*)someString actualValuesOnly:(BOOL)actualValuesOnly {
static NSString *prevSsomeString;
static BOOL prevActualValuesOnly;
static NSArray *prevResults
if ([someString isEqualToString:prevSomeString] &&
([actualValuesOnly isEqual: prevActualValuesOnly])
// HOW TO COMPARE THESE TWO BOOLEANS CORRECTLY??
{ return prevResults; }// parameters have not changed, return previous results
else { } // do calculations and store parameters and results for future comparisons)
What would be the correct way to do this?
Since BOOL is a primitive (or scalar) type, and not a class, you can compare it directly with ==
if ([someString isEqualToString:prevSomeString] && actualValuesOnly == prevActualValuesOnly)
Boolean variable is compare with == sign instead of isEqual
if(Bool1 == Bool2){
// do something here}
Boolean is compare with == sign instead of isequal:
The solutions mentioned here are not the safest way to compare 2 BOOL values, because a BOOL is really just an integer, so they can contain more than just YES/NO values. The best way is to XOR them together, like detailed here: https://stackoverflow.com/a/11135879/1026573
As Matthias Bauch suggests,
Simply do the comparison using == operator i.e
if (BOOL1 == BOOL2)
{
//enter code here
}
Maybe my title is a little bit confusing so I'll illustrate with a scenario
Let say I want to compare between 2 int values and return me a boolean based on the logical comparison.
if (int1 > int2) return true;
if (int3 < int4) return true;
if (int5 == int6) return true;
if (int7 >= int8) return true;
if (int9 <= int10) return true;
But instead of writing this manually, I wish to do something like
- (bool)compareVal1: (int)val1 withVal2: (int)val2 usingLogical: (NSString*)logic
{
if (val1 "logic" val2) return true;
}
I want a general function which can be used to represent the 5 logical comparison that I want.
I'm not sure whether this is achievable but if you have any other solutions, please advise :)
Well first off, I would use an enum instead of an NSString to decide which logical operator to use. So try something like this:
typedef enum {
GREATER_THAN,
LESS_THAN,
LESS_THAN_OR_EQUAL,
GREATER_THAN_OR_EQUAL,
EQUALS
} logicalOperator;
And the actual function would look like this:
+ (bool)compareVal1: (int)val1 withVal2: (int)val2 usingLogical: (logicalOperator)op
{
switch(op) {
case GREATER_THAN:
return (val1 > val2);
case LESS_THAN:
return (val1 < val2);
case LESS_THAN_OR_EQUAL:
return (val1 <= val2);
case GREATER_THAN_OR_EQUAL:
return (val1 >= val2);
case EQUALS:
return (val1 == val2);
}
}
I would also make the function a static/class function because it does not truly affect a specific instance of a class, but rather it is a utility function that operates on the values passed in. An example of this functions usage would be this:
bool isGreater = [MyClass compareVal1: 4 withVal2: 3 usingLogical: GREATER_THAN];
Not sure why you can't just directly parse the string and return the result of the expression. For example (only illustrating two operators):
- (bool)compareVal1: (int)val1 withVal2: (int)val2 usingLogical: (NSString*)operator
{
if([operator isEqualTo:#">"])
{
return (val1 > val2);
}
else if ([operator isEqualTo:#"<"])
{
return (val1 < val2);
}
// similar logic statements for other operators
}
More pertinently, though, why do you need a method to do this when you can just write the evaluation itself instead?