Commit 3a477262 authored by Miro Knejp's avatar Miro Knejp Committed by Jacob Potter

Generate record operator== and operator< as friend non-member functions instead of member functions

- Follows the idiomatic way of std::tuple
- Implement operator>, operator<= and operator>= only using operator<
parent 6d79895c
......@@ -190,22 +190,25 @@ class CppGenerator(spec: Spec) extends Generator(spec) {
w.wl(marshal.fieldType(f.ty) + " " + idCpp.field(f.ident) + ";")
}
w.wl
if (r.derivingTypes.contains(DerivingType.Eq)) {
w.wl(s"bool operator==(const $actualSelf & other) const;")
w.wl(s"bool operator!=(const $actualSelf & other) const;")
w.wl
w.wl(s"friend bool operator==(const $actualSelf& lhs, const $actualSelf& rhs);")
w.wl(s"friend bool operator!=(const $actualSelf& lhs, const $actualSelf& rhs);")
}
if (r.derivingTypes.contains(DerivingType.Ord)) {
w.wl(s"bool operator<(const $actualSelf & other) const;")
w.wl(s"bool operator>(const $actualSelf & other) const;")
w.wl
w.wl(s"friend bool operator<(const $actualSelf& lhs, const $actualSelf& rhs);")
w.wl(s"friend bool operator>(const $actualSelf& lhs, const $actualSelf& rhs);")
}
if (r.derivingTypes.contains(DerivingType.Eq) && r.derivingTypes.contains(DerivingType.Ord)) {
w.wl(s"bool operator<=(const $actualSelf & other) const;")
w.wl(s"bool operator>=(const $actualSelf & other) const;")
w.wl
w.wl(s"friend bool operator<=(const $actualSelf& lhs, const $actualSelf& rhs);")
w.wl(s"friend bool operator>=(const $actualSelf& lhs, const $actualSelf& rhs);")
}
// Constructor.
if(r.fields.nonEmpty) {
w.wl
writeAlignedCall(w, actualSelf + "(", r.fields, ")", f => marshal.fieldType(f.ty) + " " + idCpp.local(f.ident))
w.wl
val init = (f: Field) => idCpp.field(f.ident) + "(std::move(" + idCpp.local(f.ident) + "))"
......@@ -229,47 +232,45 @@ class CppGenerator(spec: Spec) extends Generator(spec) {
if (r.derivingTypes.contains(DerivingType.Eq)) {
w.wl
w.w(s"bool $actualSelf::operator==(const $actualSelf & other) const").braced {
w.w("return ").nested {
val skipFirst = SkipFirst()
for (f <- r.fields) {
skipFirst { w.wl(" &&") }
w.w(s"${idCpp.field(f.ident)} == other.${idCpp.field(f.ident)}")
}
w.w(s"bool operator==(const $actualSelf& lhs, const $actualSelf& rhs)").braced {
if(!r.fields.isEmpty) {
writeAlignedCall(w, "return ", r.fields, " &&", "", f => s"lhs.${idCpp.field(f.ident)} == rhs.${idCpp.field(f.ident)}")
w.wl(";")
}
} else {
w.wl("return true;")
}
}
w.wl
w.w(s"bool $actualSelf::operator!=(const $actualSelf & other) const").braced {
w.wl("return !(*this == other);")
w.w(s"bool operator!=(const $actualSelf& lhs, const $actualSelf& rhs)").braced {
w.wl("return !(lhs == rhs);")
}
}
if (r.derivingTypes.contains(DerivingType.Ord)) {
w.wl
w.w(s"bool $actualSelf::operator<(const $actualSelf & other) const").braced {
for (f <- r.fields) {
w.w(s"if (${idCpp.field(f.ident)} < other.${idCpp.field(f.ident)})").braced {
w.w(s"bool operator<(const $actualSelf& lhs, const $actualSelf& rhs)").braced {
for(f <- r.fields) {
w.w(s"if (lhs.${idCpp.field(f.ident)} < rhs.${idCpp.field(f.ident)})").braced {
w.wl("return true;")
}
w.w(s"if (other.${idCpp.field(f.ident)} < ${idCpp.field(f.ident)})").braced {
w.w(s"if (rhs.${idCpp.field(f.ident)} < lhs.${idCpp.field(f.ident)})").braced {
w.wl("return false;")
}
}
w.wl("return false;")
}
w.wl
w.w(s"bool $actualSelf::operator>(const $actualSelf & other) const").braced {
w.wl("return other < *this;")
w.w(s"bool operator>(const $actualSelf& lhs, const $actualSelf& rhs)").braced {
w.wl("return rhs < lhs;")
}
}
if (r.derivingTypes.contains(DerivingType.Eq) && r.derivingTypes.contains(DerivingType.Ord)) {
w.wl
w.w(s"bool $actualSelf::operator<=(const $actualSelf & other) const").braced {
w.wl("return (*this < other || *this == other);")
w.w(s"bool operator<=(const $actualSelf& lhs, const $actualSelf& rhs)").braced {
w.wl("return !(rhs < lhs);")
}
w.wl
w.w(s"bool $actualSelf::operator>=(const $actualSelf & other) const").braced {
w.wl("return other <= *this;")
w.w(s"bool operator>=(const $actualSelf& lhs, const $actualSelf& rhs)").braced {
w.wl("return !(lhs < rhs);")
}
}
})
......
......@@ -295,16 +295,19 @@ abstract class Generator(spec: Spec)
case Some(s) => "::" + s + "::" + t
}
def writeAlignedCall(w: IndentWriter, call: String, params: Seq[Field], end: String, f: Field => String) = {
def writeAlignedCall(w: IndentWriter, call: String, params: Seq[Field], delim: String, end: String, f: Field => String): IndentWriter = {
w.w(call)
val skipFirst = new SkipFirst
params.foreach(p => {
skipFirst { w.wl(","); w.w(" " * call.length()) }
skipFirst { w.wl(delim); w.w(" " * call.length()) }
w.w(f(p))
})
w.w(end)
}
def writeAlignedCall(w: IndentWriter, call: String, params: Seq[Field], end: String, f: Field => String): IndentWriter =
writeAlignedCall(w, call, params, ",", end, f)
def writeAlignedObjcCall(w: IndentWriter, call: String, params: Seq[Field], end: String, f: Field => (String, String)) = {
w.w(call)
val skipFirst = new SkipFirst
......
......@@ -4,17 +4,17 @@
#include "assorted_integers.hpp" // my header
bool AssortedIntegers::operator==(const AssortedIntegers & other) const {
return eight == other.eight &&
sixteen == other.sixteen &&
thirtytwo == other.thirtytwo &&
sixtyfour == other.sixtyfour &&
o_eight == other.o_eight &&
o_sixteen == other.o_sixteen &&
o_thirtytwo == other.o_thirtytwo &&
o_sixtyfour == other.o_sixtyfour;
bool operator==(const AssortedIntegers& lhs, const AssortedIntegers& rhs) {
return lhs.eight == rhs.eight &&
lhs.sixteen == rhs.sixteen &&
lhs.thirtytwo == rhs.thirtytwo &&
lhs.sixtyfour == rhs.sixtyfour &&
lhs.o_eight == rhs.o_eight &&
lhs.o_sixteen == rhs.o_sixteen &&
lhs.o_thirtytwo == rhs.o_thirtytwo &&
lhs.o_sixtyfour == rhs.o_sixtyfour;
}
bool AssortedIntegers::operator!=(const AssortedIntegers & other) const {
return !(*this == other);
bool operator!=(const AssortedIntegers& lhs, const AssortedIntegers& rhs) {
return !(lhs == rhs);
}
......@@ -17,8 +17,9 @@ struct AssortedIntegers final {
std::experimental::optional<int32_t> o_thirtytwo;
std::experimental::optional<int64_t> o_sixtyfour;
bool operator==(const AssortedIntegers & other) const;
bool operator!=(const AssortedIntegers & other) const;
friend bool operator==(const AssortedIntegers& lhs, const AssortedIntegers& rhs);
friend bool operator!=(const AssortedIntegers& lhs, const AssortedIntegers& rhs);
AssortedIntegers(int8_t eight,
int16_t sixteen,
int32_t thirtytwo,
......
......@@ -4,39 +4,39 @@
#include "record_with_derivings.hpp" // my header
bool RecordWithDerivings::operator==(const RecordWithDerivings & other) const {
return key1 == other.key1 &&
key2 == other.key2;
bool operator==(const RecordWithDerivings& lhs, const RecordWithDerivings& rhs) {
return lhs.key1 == rhs.key1 &&
lhs.key2 == rhs.key2;
}
bool RecordWithDerivings::operator!=(const RecordWithDerivings & other) const {
return !(*this == other);
bool operator!=(const RecordWithDerivings& lhs, const RecordWithDerivings& rhs) {
return !(lhs == rhs);
}
bool RecordWithDerivings::operator<(const RecordWithDerivings & other) const {
if (key1 < other.key1) {
bool operator<(const RecordWithDerivings& lhs, const RecordWithDerivings& rhs) {
if (lhs.key1 < rhs.key1) {
return true;
}
if (other.key1 < key1) {
if (rhs.key1 < lhs.key1) {
return false;
}
if (key2 < other.key2) {
if (lhs.key2 < rhs.key2) {
return true;
}
if (other.key2 < key2) {
if (rhs.key2 < lhs.key2) {
return false;
}
return false;
}
bool RecordWithDerivings::operator>(const RecordWithDerivings & other) const {
return other < *this;
bool operator>(const RecordWithDerivings& lhs, const RecordWithDerivings& rhs) {
return rhs < lhs;
}
bool RecordWithDerivings::operator<=(const RecordWithDerivings & other) const {
return (*this < other || *this == other);
bool operator<=(const RecordWithDerivings& lhs, const RecordWithDerivings& rhs) {
return !(rhs < lhs);
}
bool RecordWithDerivings::operator>=(const RecordWithDerivings & other) const {
return other <= *this;
bool operator>=(const RecordWithDerivings& lhs, const RecordWithDerivings& rhs) {
return !(lhs < rhs);
}
......@@ -11,12 +11,15 @@ struct RecordWithDerivings final {
int32_t key1;
std::string key2;
bool operator==(const RecordWithDerivings & other) const;
bool operator!=(const RecordWithDerivings & other) const;
bool operator<(const RecordWithDerivings & other) const;
bool operator>(const RecordWithDerivings & other) const;
bool operator<=(const RecordWithDerivings & other) const;
bool operator>=(const RecordWithDerivings & other) const;
friend bool operator==(const RecordWithDerivings& lhs, const RecordWithDerivings& rhs);
friend bool operator!=(const RecordWithDerivings& lhs, const RecordWithDerivings& rhs);
friend bool operator<(const RecordWithDerivings& lhs, const RecordWithDerivings& rhs);
friend bool operator>(const RecordWithDerivings& lhs, const RecordWithDerivings& rhs);
friend bool operator<=(const RecordWithDerivings& lhs, const RecordWithDerivings& rhs);
friend bool operator>=(const RecordWithDerivings& lhs, const RecordWithDerivings& rhs);
RecordWithDerivings(int32_t key1,
std::string key2)
: key1(std::move(key1))
......
......@@ -4,39 +4,39 @@
#include "record_with_nested_derivings.hpp" // my header
bool RecordWithNestedDerivings::operator==(const RecordWithNestedDerivings & other) const {
return key == other.key &&
rec == other.rec;
bool operator==(const RecordWithNestedDerivings& lhs, const RecordWithNestedDerivings& rhs) {
return lhs.key == rhs.key &&
lhs.rec == rhs.rec;
}
bool RecordWithNestedDerivings::operator!=(const RecordWithNestedDerivings & other) const {
return !(*this == other);
bool operator!=(const RecordWithNestedDerivings& lhs, const RecordWithNestedDerivings& rhs) {
return !(lhs == rhs);
}
bool RecordWithNestedDerivings::operator<(const RecordWithNestedDerivings & other) const {
if (key < other.key) {
bool operator<(const RecordWithNestedDerivings& lhs, const RecordWithNestedDerivings& rhs) {
if (lhs.key < rhs.key) {
return true;
}
if (other.key < key) {
if (rhs.key < lhs.key) {
return false;
}
if (rec < other.rec) {
if (lhs.rec < rhs.rec) {
return true;
}
if (other.rec < rec) {
if (rhs.rec < lhs.rec) {
return false;
}
return false;
}
bool RecordWithNestedDerivings::operator>(const RecordWithNestedDerivings & other) const {
return other < *this;
bool operator>(const RecordWithNestedDerivings& lhs, const RecordWithNestedDerivings& rhs) {
return rhs < lhs;
}
bool RecordWithNestedDerivings::operator<=(const RecordWithNestedDerivings & other) const {
return (*this < other || *this == other);
bool operator<=(const RecordWithNestedDerivings& lhs, const RecordWithNestedDerivings& rhs) {
return !(rhs < lhs);
}
bool RecordWithNestedDerivings::operator>=(const RecordWithNestedDerivings & other) const {
return other <= *this;
bool operator>=(const RecordWithNestedDerivings& lhs, const RecordWithNestedDerivings& rhs) {
return !(lhs < rhs);
}
......@@ -11,12 +11,15 @@ struct RecordWithNestedDerivings final {
int32_t key;
RecordWithDerivings rec;
bool operator==(const RecordWithNestedDerivings & other) const;
bool operator!=(const RecordWithNestedDerivings & other) const;
bool operator<(const RecordWithNestedDerivings & other) const;
bool operator>(const RecordWithNestedDerivings & other) const;
bool operator<=(const RecordWithNestedDerivings & other) const;
bool operator>=(const RecordWithNestedDerivings & other) const;
friend bool operator==(const RecordWithNestedDerivings& lhs, const RecordWithNestedDerivings& rhs);
friend bool operator!=(const RecordWithNestedDerivings& lhs, const RecordWithNestedDerivings& rhs);
friend bool operator<(const RecordWithNestedDerivings& lhs, const RecordWithNestedDerivings& rhs);
friend bool operator>(const RecordWithNestedDerivings& lhs, const RecordWithNestedDerivings& rhs);
friend bool operator<=(const RecordWithNestedDerivings& lhs, const RecordWithNestedDerivings& rhs);
friend bool operator>=(const RecordWithNestedDerivings& lhs, const RecordWithNestedDerivings& rhs);
RecordWithNestedDerivings(int32_t key,
RecordWithDerivings rec)
: key(std::move(key))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment