diff --git a/src/util/lexcmp_def.hpp b/src/util/lexcmp_def.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0cc7e66d0b9cdce347a7b5bac9d89fb50fe0de5b --- /dev/null +++ b/src/util/lexcmp_def.hpp @@ -0,0 +1,31 @@ +#pragma once + +/* + * Macro definitions for defining comparison operators for + * record-like types. + * + * Use: + * + * To define comparison operations for a record type xyzzy + * with fields foo, bar and baz: + * + * DEFINE_LEXICOGRAPHIC_ORDERING(xyzzy,(a.foo,a.bar,a.baz),(b.foo,b.bar,b.baz)) + * + * The explicit use of 'a' and 'b' in the second and third parameters + * is needed only to save a heroic amount of preprocessor macro + * deep magic. + * + */ + +#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(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) diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index a3a2d55333f6316b133bff3982ec58e1b03d525d..61d713bc831e7ec63dfaf370f7931e204c7d9e45 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -16,6 +16,7 @@ set(TEST_SOURCES test_event_queue.cpp test_fvm.cpp test_cell_group.cpp + test_lexcmp.cpp test_matrix.cpp test_mechanisms.cpp test_optional.cpp diff --git a/tests/unit/test_lexcmp.cpp b/tests/unit/test_lexcmp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..300372391de1d69016eec827cf03ef1e46c30dfb --- /dev/null +++ b/tests/unit/test_lexcmp.cpp @@ -0,0 +1,58 @@ +#include "gtest.h" + +#include <util/lexcmp_def.hpp> + +struct lexcmp_test_one { + int foo; +}; + +DEFINE_LEXICOGRAPHIC_ORDERING(lexcmp_test_one, (a.foo), (b.foo)) + +TEST(lexcmp_def,one) { + lexcmp_test_one p{3}, q{4}, r{4}; + + EXPECT_LE(p,q); + EXPECT_LT(p,q); + EXPECT_NE(p,q); + EXPECT_GE(q,p); + EXPECT_GT(q,p); + + EXPECT_LE(q,r); + EXPECT_GE(q,r); + EXPECT_EQ(q,r); +} + +struct lexcmp_test_three { + int x; + std::string y; + double z; +}; + +// test fields in reverse order: z, y, x +DEFINE_LEXICOGRAPHIC_ORDERING(lexcmp_test_three, (a.z,a.y,a.x), (b.z,b.y,b.x)) + +TEST(lexcmp_def,three) { + lexcmp_test_three p{1,"foo",2}; + lexcmp_test_three q{1,"foo",3}; + lexcmp_test_three r{1,"bar",2}; + lexcmp_test_three s{5,"foo",2}; + + EXPECT_LE(p,q); + EXPECT_LT(p,q); + EXPECT_NE(p,q); + EXPECT_GE(q,p); + EXPECT_GT(q,p); + + EXPECT_LE(r,p); + EXPECT_LT(r,p); + EXPECT_NE(p,r); + EXPECT_GE(p,r); + EXPECT_GT(p,r); + + EXPECT_LE(p,s); + EXPECT_LT(p,s); + EXPECT_NE(p,s); + EXPECT_GE(s,p); + EXPECT_GT(s,p); +} +