From 25a8bc45224337ad77310b2032e53ee7b09b978d Mon Sep 17 00:00:00 2001
From: Sam Yates <halfflat@gmail.com>
Date: Thu, 28 Jul 2016 16:55:24 +0200
Subject: [PATCH] Extend lexicographic ordering tests, functionality.

* Test comparison by ref-returning member function.
* Add a 'BY_VALUE' version of the macro, that performs
  the comparison via proxy tuples, allowing comparisons
  via a sequence of arbitrary expressions (including
  non-reference returning member functions).
---
 src/util/lexcmp_def.hpp    | 25 ++++++++++++------
 tests/unit/test_lexcmp.cpp | 52 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 69 insertions(+), 8 deletions(-)

diff --git a/src/util/lexcmp_def.hpp b/src/util/lexcmp_def.hpp
index 0cc7e66d..d1c3e8a3 100644
--- a/src/util/lexcmp_def.hpp
+++ b/src/util/lexcmp_def.hpp
@@ -19,13 +19,22 @@
 
 #include <tuple>
 
-#define DEFINE_LEXICOGRAPHIC_ORDERING_IMPL_(op,type,a_fields,b_fields) \
-inline bool operator op(const type &a,const type &b) { return std::tie a_fields op std::tie b_fields; }
+#define DEFINE_LEXICOGRAPHIC_ORDERING_IMPL_(proxy,op,type,a_fields,b_fields) \
+inline bool operator op(const type &a,const type &b) { return proxy a_fields op proxy b_fields; }
 
 #define DEFINE_LEXICOGRAPHIC_ORDERING(type,a_fields,b_fields) \
-DEFINE_LEXICOGRAPHIC_ORDERING_IMPL_(<,type,a_fields,b_fields) \
-DEFINE_LEXICOGRAPHIC_ORDERING_IMPL_(>,type,a_fields,b_fields) \
-DEFINE_LEXICOGRAPHIC_ORDERING_IMPL_(<=,type,a_fields,b_fields) \
-DEFINE_LEXICOGRAPHIC_ORDERING_IMPL_(>=,type,a_fields,b_fields) \
-DEFINE_LEXICOGRAPHIC_ORDERING_IMPL_(!=,type,a_fields,b_fields) \
-DEFINE_LEXICOGRAPHIC_ORDERING_IMPL_(==,type,a_fields,b_fields)
+DEFINE_LEXICOGRAPHIC_ORDERING_IMPL_(std::tie,<,type,a_fields,b_fields) \
+DEFINE_LEXICOGRAPHIC_ORDERING_IMPL_(std::tie,>,type,a_fields,b_fields) \
+DEFINE_LEXICOGRAPHIC_ORDERING_IMPL_(std::tie,<=,type,a_fields,b_fields) \
+DEFINE_LEXICOGRAPHIC_ORDERING_IMPL_(std::tie,>=,type,a_fields,b_fields) \
+DEFINE_LEXICOGRAPHIC_ORDERING_IMPL_(std::tie,!=,type,a_fields,b_fields) \
+DEFINE_LEXICOGRAPHIC_ORDERING_IMPL_(std::tie,==,type,a_fields,b_fields)
+
+#define DEFINE_LEXICOGRAPHIC_ORDERING_BY_VALUE(type,a_fields,b_fields) \
+DEFINE_LEXICOGRAPHIC_ORDERING_IMPL_(std::make_tuple,<,type,a_fields,b_fields) \
+DEFINE_LEXICOGRAPHIC_ORDERING_IMPL_(std::make_tuple,>,type,a_fields,b_fields) \
+DEFINE_LEXICOGRAPHIC_ORDERING_IMPL_(std::make_tuple,<=,type,a_fields,b_fields) \
+DEFINE_LEXICOGRAPHIC_ORDERING_IMPL_(std::make_tuple,>=,type,a_fields,b_fields) \
+DEFINE_LEXICOGRAPHIC_ORDERING_IMPL_(std::make_tuple,!=,type,a_fields,b_fields) \
+DEFINE_LEXICOGRAPHIC_ORDERING_IMPL_(std::make_tuple,==,type,a_fields,b_fields)
+
diff --git a/tests/unit/test_lexcmp.cpp b/tests/unit/test_lexcmp.cpp
index 30037239..a02ac076 100644
--- a/tests/unit/test_lexcmp.cpp
+++ b/tests/unit/test_lexcmp.cpp
@@ -56,3 +56,55 @@ TEST(lexcmp_def,three) {
     EXPECT_GT(s,p);
 }
 
+// test fields accessed by reference-returning member function
+
+class lexcmp_test_refmemfn {
+public:
+    explicit lexcmp_test_refmemfn(int foo): foo_(foo) {}
+
+    const int &foo() const { return foo_; }
+    int &foo() { return foo_; }
+
+private:
+    int foo_;
+};
+
+DEFINE_LEXICOGRAPHIC_ORDERING(lexcmp_test_refmemfn, (a.foo()), (b.foo()))
+
+TEST(lexcmp_def,refmemfn) {
+    lexcmp_test_refmemfn p{3};
+    const lexcmp_test_refmemfn q{4};
+
+    EXPECT_LE(p,q);
+    EXPECT_LT(p,q);
+    EXPECT_NE(p,q);
+    EXPECT_GE(q,p);
+    EXPECT_GT(q,p);
+}
+
+// test comparison via proxy tuple object
+
+class lexcmp_test_valmemfn {
+public:
+    explicit lexcmp_test_valmemfn(int foo, int bar): foo_(foo), bar_(bar) {}
+    int foo() const { return foo_; }
+    int bar() const { return bar_; }
+
+private:
+    int foo_;
+    int bar_;
+};
+
+DEFINE_LEXICOGRAPHIC_ORDERING_BY_VALUE(lexcmp_test_valmemfn, (a.foo(),a.bar()), (b.foo(),b.bar()))
+
+TEST(lexcmp_def,proxy) {
+    lexcmp_test_valmemfn p{3,2}, q{3,4};
+
+    EXPECT_LE(p,q);
+    EXPECT_LT(p,q);
+    EXPECT_NE(p,q);
+    EXPECT_GE(q,p);
+    EXPECT_GT(q,p);
+}
+
+
-- 
GitLab