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) { ...@@ -190,22 +190,25 @@ class CppGenerator(spec: Spec) extends Generator(spec) {
w.wl(marshal.fieldType(f.ty) + " " + idCpp.field(f.ident) + ";") w.wl(marshal.fieldType(f.ty) + " " + idCpp.field(f.ident) + ";")
} }
w.wl
if (r.derivingTypes.contains(DerivingType.Eq)) { if (r.derivingTypes.contains(DerivingType.Eq)) {
w.wl(s"bool operator==(const $actualSelf & other) const;") w.wl
w.wl(s"bool operator!=(const $actualSelf & other) const;") 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)) { if (r.derivingTypes.contains(DerivingType.Ord)) {
w.wl(s"bool operator<(const $actualSelf & other) const;") w.wl
w.wl(s"bool operator>(const $actualSelf & other) const;") 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)) { if (r.derivingTypes.contains(DerivingType.Eq) && r.derivingTypes.contains(DerivingType.Ord)) {
w.wl(s"bool operator<=(const $actualSelf & other) const;") w.wl
w.wl(s"bool operator>=(const $actualSelf & other) const;") 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. // Constructor.
if(r.fields.nonEmpty) { if(r.fields.nonEmpty) {
w.wl
writeAlignedCall(w, actualSelf + "(", r.fields, ")", f => marshal.fieldType(f.ty) + " " + idCpp.local(f.ident)) writeAlignedCall(w, actualSelf + "(", r.fields, ")", f => marshal.fieldType(f.ty) + " " + idCpp.local(f.ident))
w.wl w.wl
val init = (f: Field) => idCpp.field(f.ident) + "(std::move(" + idCpp.local(f.ident) + "))" 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) { ...@@ -229,47 +232,45 @@ class CppGenerator(spec: Spec) extends Generator(spec) {
if (r.derivingTypes.contains(DerivingType.Eq)) { if (r.derivingTypes.contains(DerivingType.Eq)) {
w.wl w.wl
w.w(s"bool $actualSelf::operator==(const $actualSelf & other) const").braced { w.w(s"bool operator==(const $actualSelf& lhs, const $actualSelf& rhs)").braced {
w.w("return ").nested { if(!r.fields.isEmpty) {
val skipFirst = SkipFirst() writeAlignedCall(w, "return ", r.fields, " &&", "", f => s"lhs.${idCpp.field(f.ident)} == rhs.${idCpp.field(f.ident)}")
for (f <- r.fields) {
skipFirst { w.wl(" &&") }
w.w(s"${idCpp.field(f.ident)} == other.${idCpp.field(f.ident)}")
}
w.wl(";") w.wl(";")
} else {
w.wl("return true;")
} }
} }
w.wl w.wl
w.w(s"bool $actualSelf::operator!=(const $actualSelf & other) const").braced { w.w(s"bool operator!=(const $actualSelf& lhs, const $actualSelf& rhs)").braced {
w.wl("return !(*this == other);") w.wl("return !(lhs == rhs);")
} }
} }
if (r.derivingTypes.contains(DerivingType.Ord)) { if (r.derivingTypes.contains(DerivingType.Ord)) {
w.wl w.wl
w.w(s"bool $actualSelf::operator<(const $actualSelf & other) const").braced { w.w(s"bool operator<(const $actualSelf& lhs, const $actualSelf& rhs)").braced {
for (f <- r.fields) { for(f <- r.fields) {
w.w(s"if (${idCpp.field(f.ident)} < other.${idCpp.field(f.ident)})").braced { w.w(s"if (lhs.${idCpp.field(f.ident)} < rhs.${idCpp.field(f.ident)})").braced {
w.wl("return true;") 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("return false;") w.wl("return false;")
} }
w.wl w.wl
w.w(s"bool $actualSelf::operator>(const $actualSelf & other) const").braced { w.w(s"bool operator>(const $actualSelf& lhs, const $actualSelf& rhs)").braced {
w.wl("return other < *this;") w.wl("return rhs < lhs;")
} }
} }
if (r.derivingTypes.contains(DerivingType.Eq) && r.derivingTypes.contains(DerivingType.Ord)) { if (r.derivingTypes.contains(DerivingType.Eq) && r.derivingTypes.contains(DerivingType.Ord)) {
w.wl w.wl
w.w(s"bool $actualSelf::operator<=(const $actualSelf & other) const").braced { w.w(s"bool operator<=(const $actualSelf& lhs, const $actualSelf& rhs)").braced {
w.wl("return (*this < other || *this == other);") w.wl("return !(rhs < lhs);")
} }
w.wl w.wl
w.w(s"bool $actualSelf::operator>=(const $actualSelf & other) const").braced { w.w(s"bool operator>=(const $actualSelf& lhs, const $actualSelf& rhs)").braced {
w.wl("return other <= *this;") w.wl("return !(lhs < rhs);")
} }
} }
}) })
......
...@@ -295,16 +295,19 @@ abstract class Generator(spec: Spec) ...@@ -295,16 +295,19 @@ abstract class Generator(spec: Spec)
case Some(s) => "::" + s + "::" + t 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) w.w(call)
val skipFirst = new SkipFirst val skipFirst = new SkipFirst
params.foreach(p => { params.foreach(p => {
skipFirst { w.wl(","); w.w(" " * call.length()) } skipFirst { w.wl(delim); w.w(" " * call.length()) }
w.w(f(p)) w.w(f(p))
}) })
w.w(end) 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)) = { def writeAlignedObjcCall(w: IndentWriter, call: String, params: Seq[Field], end: String, f: Field => (String, String)) = {
w.w(call) w.w(call)
val skipFirst = new SkipFirst val skipFirst = new SkipFirst
......
...@@ -4,17 +4,17 @@ ...@@ -4,17 +4,17 @@
#include "assorted_integers.hpp" // my header #include "assorted_integers.hpp" // my header
bool AssortedIntegers::operator==(const AssortedIntegers & other) const { bool operator==(const AssortedIntegers& lhs, const AssortedIntegers& rhs) {
return eight == other.eight && return lhs.eight == rhs.eight &&
sixteen == other.sixteen && lhs.sixteen == rhs.sixteen &&
thirtytwo == other.thirtytwo && lhs.thirtytwo == rhs.thirtytwo &&
sixtyfour == other.sixtyfour && lhs.sixtyfour == rhs.sixtyfour &&
o_eight == other.o_eight && lhs.o_eight == rhs.o_eight &&
o_sixteen == other.o_sixteen && lhs.o_sixteen == rhs.o_sixteen &&
o_thirtytwo == other.o_thirtytwo && lhs.o_thirtytwo == rhs.o_thirtytwo &&
o_sixtyfour == other.o_sixtyfour; lhs.o_sixtyfour == rhs.o_sixtyfour;
} }
bool AssortedIntegers::operator!=(const AssortedIntegers & other) const { bool operator!=(const AssortedIntegers& lhs, const AssortedIntegers& rhs) {
return !(*this == other); return !(lhs == rhs);
} }
...@@ -17,8 +17,9 @@ struct AssortedIntegers final { ...@@ -17,8 +17,9 @@ struct AssortedIntegers final {
std::experimental::optional<int32_t> o_thirtytwo; std::experimental::optional<int32_t> o_thirtytwo;
std::experimental::optional<int64_t> o_sixtyfour; std::experimental::optional<int64_t> o_sixtyfour;
bool operator==(const AssortedIntegers & other) const; friend bool operator==(const AssortedIntegers& lhs, const AssortedIntegers& rhs);
bool operator!=(const AssortedIntegers & other) const; friend bool operator!=(const AssortedIntegers& lhs, const AssortedIntegers& rhs);
AssortedIntegers(int8_t eight, AssortedIntegers(int8_t eight,
int16_t sixteen, int16_t sixteen,
int32_t thirtytwo, int32_t thirtytwo,
......
...@@ -4,39 +4,39 @@ ...@@ -4,39 +4,39 @@
#include "record_with_derivings.hpp" // my header #include "record_with_derivings.hpp" // my header
bool RecordWithDerivings::operator==(const RecordWithDerivings & other) const { bool operator==(const RecordWithDerivings& lhs, const RecordWithDerivings& rhs) {
return key1 == other.key1 && return lhs.key1 == rhs.key1 &&
key2 == other.key2; lhs.key2 == rhs.key2;
} }
bool RecordWithDerivings::operator!=(const RecordWithDerivings & other) const { bool operator!=(const RecordWithDerivings& lhs, const RecordWithDerivings& rhs) {
return !(*this == other); return !(lhs == rhs);
} }
bool RecordWithDerivings::operator<(const RecordWithDerivings & other) const { bool operator<(const RecordWithDerivings& lhs, const RecordWithDerivings& rhs) {
if (key1 < other.key1) { if (lhs.key1 < rhs.key1) {
return true; return true;
} }
if (other.key1 < key1) { if (rhs.key1 < lhs.key1) {
return false; return false;
} }
if (key2 < other.key2) { if (lhs.key2 < rhs.key2) {
return true; return true;
} }
if (other.key2 < key2) { if (rhs.key2 < lhs.key2) {
return false; return false;
} }
return false; return false;
} }
bool RecordWithDerivings::operator>(const RecordWithDerivings & other) const { bool operator>(const RecordWithDerivings& lhs, const RecordWithDerivings& rhs) {
return other < *this; return rhs < lhs;
} }
bool RecordWithDerivings::operator<=(const RecordWithDerivings & other) const { bool operator<=(const RecordWithDerivings& lhs, const RecordWithDerivings& rhs) {
return (*this < other || *this == other); return !(rhs < lhs);
} }
bool RecordWithDerivings::operator>=(const RecordWithDerivings & other) const { bool operator>=(const RecordWithDerivings& lhs, const RecordWithDerivings& rhs) {
return other <= *this; return !(lhs < rhs);
} }
...@@ -11,12 +11,15 @@ struct RecordWithDerivings final { ...@@ -11,12 +11,15 @@ struct RecordWithDerivings final {
int32_t key1; int32_t key1;
std::string key2; std::string key2;
bool operator==(const RecordWithDerivings & other) const; friend bool operator==(const RecordWithDerivings& lhs, const RecordWithDerivings& rhs);
bool operator!=(const RecordWithDerivings & other) const; friend bool operator!=(const RecordWithDerivings& lhs, const RecordWithDerivings& rhs);
bool operator<(const RecordWithDerivings & other) const;
bool operator>(const RecordWithDerivings & other) const; friend bool operator<(const RecordWithDerivings& lhs, const RecordWithDerivings& rhs);
bool operator<=(const RecordWithDerivings & other) const; friend bool operator>(const RecordWithDerivings& lhs, const RecordWithDerivings& rhs);
bool operator>=(const RecordWithDerivings & other) const;
friend bool operator<=(const RecordWithDerivings& lhs, const RecordWithDerivings& rhs);
friend bool operator>=(const RecordWithDerivings& lhs, const RecordWithDerivings& rhs);
RecordWithDerivings(int32_t key1, RecordWithDerivings(int32_t key1,
std::string key2) std::string key2)
: key1(std::move(key1)) : key1(std::move(key1))
......
...@@ -4,39 +4,39 @@ ...@@ -4,39 +4,39 @@
#include "record_with_nested_derivings.hpp" // my header #include "record_with_nested_derivings.hpp" // my header
bool RecordWithNestedDerivings::operator==(const RecordWithNestedDerivings & other) const { bool operator==(const RecordWithNestedDerivings& lhs, const RecordWithNestedDerivings& rhs) {
return key == other.key && return lhs.key == rhs.key &&
rec == other.rec; lhs.rec == rhs.rec;
} }
bool RecordWithNestedDerivings::operator!=(const RecordWithNestedDerivings & other) const { bool operator!=(const RecordWithNestedDerivings& lhs, const RecordWithNestedDerivings& rhs) {
return !(*this == other); return !(lhs == rhs);
} }
bool RecordWithNestedDerivings::operator<(const RecordWithNestedDerivings & other) const { bool operator<(const RecordWithNestedDerivings& lhs, const RecordWithNestedDerivings& rhs) {
if (key < other.key) { if (lhs.key < rhs.key) {
return true; return true;
} }
if (other.key < key) { if (rhs.key < lhs.key) {
return false; return false;
} }
if (rec < other.rec) { if (lhs.rec < rhs.rec) {
return true; return true;
} }
if (other.rec < rec) { if (rhs.rec < lhs.rec) {
return false; return false;
} }
return false; return false;
} }
bool RecordWithNestedDerivings::operator>(const RecordWithNestedDerivings & other) const { bool operator>(const RecordWithNestedDerivings& lhs, const RecordWithNestedDerivings& rhs) {
return other < *this; return rhs < lhs;
} }
bool RecordWithNestedDerivings::operator<=(const RecordWithNestedDerivings & other) const { bool operator<=(const RecordWithNestedDerivings& lhs, const RecordWithNestedDerivings& rhs) {
return (*this < other || *this == other); return !(rhs < lhs);
} }
bool RecordWithNestedDerivings::operator>=(const RecordWithNestedDerivings & other) const { bool operator>=(const RecordWithNestedDerivings& lhs, const RecordWithNestedDerivings& rhs) {
return other <= *this; return !(lhs < rhs);
} }
...@@ -11,12 +11,15 @@ struct RecordWithNestedDerivings final { ...@@ -11,12 +11,15 @@ struct RecordWithNestedDerivings final {
int32_t key; int32_t key;
RecordWithDerivings rec; RecordWithDerivings rec;
bool operator==(const RecordWithNestedDerivings & other) const; friend bool operator==(const RecordWithNestedDerivings& lhs, const RecordWithNestedDerivings& rhs);
bool operator!=(const RecordWithNestedDerivings & other) const; friend bool operator!=(const RecordWithNestedDerivings& lhs, const RecordWithNestedDerivings& rhs);
bool operator<(const RecordWithNestedDerivings & other) const;
bool operator>(const RecordWithNestedDerivings & other) const; friend bool operator<(const RecordWithNestedDerivings& lhs, const RecordWithNestedDerivings& rhs);
bool operator<=(const RecordWithNestedDerivings & other) const; friend bool operator>(const RecordWithNestedDerivings& lhs, const RecordWithNestedDerivings& rhs);
bool operator>=(const RecordWithNestedDerivings & other) const;
friend bool operator<=(const RecordWithNestedDerivings& lhs, const RecordWithNestedDerivings& rhs);
friend bool operator>=(const RecordWithNestedDerivings& lhs, const RecordWithNestedDerivings& rhs);
RecordWithNestedDerivings(int32_t key, RecordWithNestedDerivings(int32_t key,
RecordWithDerivings rec) RecordWithDerivings rec)
: key(std::move(key)) : 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