#reduce number of comparision operator overloads; c++17

76 messages · Page 1 of 1 (latest)

silver wing
#

I have several operator overloads that can be simplified to

bool operator OP (const Rational& lhs, const Rational& rhs)
{
  if(lhs.denominator == rhs.denominator)
    return lhs.numerator OP rhs.numerator;

  const int n_l = lhs.numerator * rhs.denominator;
  const int n_r = rhs.numerator * lhs.denominator;
  return n_l OP n_r;
}

is it possible to generate all of them at once using something from c++ or do I have to use macros?

note that i have to stick with c++17 so i cannot use operator<=>

waxen boneBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question run !howto ask.

desert nacelle
#

all you need is < and ==
!= => !(x==y)
>= => !(x<y)
<= => (x<y)||(x==y)
> => !(x<=y)

vernal rivet
#

I don't entirely understand the question

#

what is OP and what does it mean to do int OP int

desert nacelle
#

OP is a comparison operator

vernal rivet
#

how do you know?

desert nacelle
#

per the title and reference to operator<=> in the question body

vernal rivet
#

oh yeah, titles are a thing, aren't they

#

usually they are shit so I don't read them 😆

desert nacelle
#

lol

vernal rivet
#

you can turn the first 4 lines into a separate function because they never change

#
tuple<int,int> unifyFractionDenominators(const Rational& lhs, const Rational& rhs) {
  if(lhs.denominator == rhs.denominator)
    return { lhs.numerator, rhs.numerator};

  const int n_l = lhs.numerator * rhs.denominator;
  const int n_r = rhs.numerator * lhs.denominator;
  return { n_l, n_r };
}
#

at least, if I have correctly assumed what you're trying to do

#

return lhs.numerator OP rhs.denominator; this bit is probably wrong

#

shouldn't those both be numerators?

round plover
vernal rivet
#

also, if that scares you, wait until you get to the real world

round plover
#

@vernal rivet humour bro ?

silver wing
vernal rivet
#

also you forgot your </sarcasm> tag

round plover
#

@silver wing would be better if you post actual code instead of pseudo code

silver wing
round plover
silver wing
silver wing
round plover
silver wing
#

edited the post

silver wing
vernal rivet
#

I guess a better name there might be unifyFractionNumerators because it's actually returning numerators, idk

#

somewhat subjective

#

the premise is all because the denominators are might be different

#

but you're returning numerators, so... 🤷

desert nacelle
#

i don't see why, if you're already doing all the logic in the helper function, you don't go all the way and do all the logic

bool do_op(const Rational& lhs, const Rational& rhs, std::function<bool(const int, const int)> OP) {
  if(lhs.denominator == rhs.denominator)
    return OP(lhs.numerator, rhs.numerator);

  const int n_l = lhs.numerator * rhs.denominator;
  const int n_r = rhs.numerator * lhs.denominator;
  return OP(n_l, n_r);
}

bool Rational::operator<(const Rational& other) const {
  return do_op(*this, other, std::less<int>{});
}
bool Rational::operator<=(const Rational& other) const {
  return !do_op(*this, other, std::greater<int>{});
}
bool Rational::operator>(const Rational& other) const {
  return do_op(*this, other, std::greater<int>{});
}
bool Rational::operator>=(const Rational& other) const {
  return !do_op(*this, other, std::less<int>{});
}
bool Rational::operator==(const Rational& other) const {
  return do_op(*this, other, std::equal_to<int>{});
}
bool Rational::operator!=(const Rational& other) const {
  return !do_op(*this, other, std::equal_to<int>{});
}
silver wing
#

does any approach here have overhead or is everything inlined and does not differ from plain function?

vernal rivet
#

or with some clevery jumpy through hoopy using compiler flags

#

generally it's likely that compilers are good at optimizing things away

#

sometimes too good in fact

silver wing
#

Alr salute

vernal rivet
#

godbol might be a good name for a russian black metal band 😉

silver wing
vernal rivet
vernal rivet
#

like doing a release build with extracted .pdb files, the compiler will probably optimize away vars you might have only had there for debugging purposes, making it more difficult to debug

#

or when doing performance benchmarking and profiling, the compiler is likely to optimize away all your code if that code doesn't "actually do something"

#

like

int main() {
  int x = 0;
  int y = x + 2;
}
desert nacelle
#

something something volatile
(never rely on volatile)

vernal rivet
#

this code will probably optimize down to nothing

#

because the variable y is unused

#

and if y is unused, then x is also unused

#

but if you wanted to benchmark the performance of +

silver wing
#

Oh in this sense

vernal rivet
#

then that's not very useful

silver wing
#

Yea had some problems with that

#

Alr thanks salute

vernal rivet
#

now this ofc, only applies if you have turned on optimizations like with -O2 and friends

#

but still

#

google benchmark has a DoNotOptimize() function specifically for this purpose

desert nacelle
#

but if you're benchmarking, it really only makes sense to do so with compiler optimizations

silver wing
#

I don't think benchmarking makes that much sense without optimizing, unless turning off specific optimizations

vernal rivet
#

indeed

#

it makes no sense

#

like, literally none

vernal rivet
#

so it could be easy to miss this and make erroneous assumptions about the resulting assembly

silver wing
#

Oh that's not a problem I've used it before

#

!solved