From 213f1986c6a8ffcc93b0b8c403b3df24548d090f Mon Sep 17 00:00:00 2001 From: Daniel Baston Date: Sat, 14 Jan 2023 20:33:17 -0500 Subject: [PATCH] CoordinateSequence: Add type-detecting forEach for use with auto lambdas --- CMakeLists.txt | 2 +- include/geos/geom/CoordinateSequence.h | 10 +++++++++ src/geom/CoordinateSequence.cpp | 17 +++++++++------ tests/unit/geom/CoordinateSequenceTest.cpp | 25 ++++++++++++++++++++++ 4 files changed, 46 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 59ce56812b..78e775fdfb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -128,7 +128,7 @@ include(CMakeDependentOption) ## CMake global variables option(BUILD_SHARED_LIBS "Build GEOS with shared libraries" ON) -set(CMAKE_CXX_STANDARD 11 CACHE STRING "C++ standard version to use (default is 11)") +set(CMAKE_CXX_STANDARD 14 CACHE STRING "C++ standard version to use (default is 11)") ## GEOS custom variables option(BUILD_BENCHMARKS "Build GEOS benchmarks" OFF) diff --git a/include/geos/geom/CoordinateSequence.h b/include/geos/geom/CoordinateSequence.h index e9ae11ca74..c7ec952440 100644 --- a/include/geos/geom/CoordinateSequence.h +++ b/include/geos/geom/CoordinateSequence.h @@ -629,6 +629,16 @@ class GEOS_DLL CoordinateSequence { } } + template + void forEach(F&& fun) const { + switch(getCoordinateType()) { + case CoordinateType::XY: for (const auto& c : items()) { fun(c); } break; + case CoordinateType::XYZ: for (const auto& c : items()) { fun(c); } break; + case CoordinateType::XYM: for (const auto& c : items()) { fun(c); } break; + case CoordinateType::XYZM: for (const auto& c : items()) { fun(c); } break; + } + } + template void forEach(F&& fun) const { diff --git a/src/geom/CoordinateSequence.cpp b/src/geom/CoordinateSequence.cpp index 30308e0bca..0ed926e9dd 100644 --- a/src/geom/CoordinateSequence.cpp +++ b/src/geom/CoordinateSequence.cpp @@ -566,16 +566,19 @@ std::ostream& operator<< (std::ostream& os, const CoordinateSequence& cs) { os << "("; - for(std::size_t i = 0, n = cs.size(); i < n; ++i) { - if(i) { + + bool writeComma = false; + auto write = [&os, &writeComma](const auto& coord) { + if (writeComma) { os << ", "; - } - if (cs.hasZ()) { - os << cs.getAt(i); } else { - os << cs.getAt(i); + writeComma = true; } - } + + os << coord; + }; + + cs.forEach(write); os << ")"; return os; diff --git a/tests/unit/geom/CoordinateSequenceTest.cpp b/tests/unit/geom/CoordinateSequenceTest.cpp index 9d4ae05609..45eb425b13 100644 --- a/tests/unit/geom/CoordinateSequenceTest.cpp +++ b/tests/unit/geom/CoordinateSequenceTest.cpp @@ -1392,4 +1392,29 @@ void object::test<52> } } +// Test type-detecting version of forEach +template<> +template<> +void object::test<53> +() +{ + CoordinateSequence dst(0u, true, true); + + CoordinateSequence src1{{Coordinate{1, 2, 3}, Coordinate{4, 5, 6}}}; + CoordinateSequence src2{{CoordinateXYM{7, 8, 9}, {10, 11, 12}}}; + + auto appendToDst = [&dst](auto& coord) { + dst.add(coord); + }; + + src1.forEach(appendToDst); + src2.forEach(appendToDst); + + ensure_equals(dst.size(), 4u); + ensure_equals_xyzm(dst.getAt(0), CoordinateXYZM{1, 2, 3, DoubleNotANumber}); + ensure_equals_xyzm(dst.getAt(1), CoordinateXYZM{4, 5, 6, DoubleNotANumber}); + ensure_equals_xyzm(dst.getAt(2), CoordinateXYZM{7, 8, DoubleNotANumber, 9}); + ensure_equals_xyzm(dst.getAt(3), CoordinateXYZM{10, 11, DoubleNotANumber, 12}); +} + } // namespace tut