Skip to content

Commit a3d72c8

Browse files
committed
CSVReader should satisfy input_range
1 parent e425b15 commit a3d72c8

File tree

5 files changed

+66
-0
lines changed

5 files changed

+66
-0
lines changed

.github/workflows/cmake-multi-platform.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ jobs:
2626
os: [windows-latest, ubuntu-latest]
2727
build_type: [Release]
2828
c_compiler: [gcc, cl]
29+
cxx_standard: [17, 20]
2930
include:
3031
- os: windows-latest
3132
c_compiler: cl
@@ -57,6 +58,7 @@ jobs:
5758
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
5859
run: >
5960
cmake -B ${{ steps.strings.outputs.build-output-dir }}
61+
-DCSV_CXX_STANDARD=${{ matrix.cxx_standard }}
6062
-DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }}
6163
-DCMAKE_C_COMPILER=${{ matrix.c_compiler }}
6264
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}

include/internal/common.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ namespace csv {
5454

5555
#define STATIC_ASSERT(x) static_assert(x, "Assertion failed")
5656

57+
#if (defined(CMAKE_CXX_STANDARD) && CMAKE_CXX_STANDARD == 20) || __cplusplus >= 202002L
58+
#define CSV_HAS_CXX20
59+
#endif
60+
5761
#if (defined(CMAKE_CXX_STANDARD) && CMAKE_CXX_STANDARD == 17) || __cplusplus >= 201703L
5862
#define CSV_HAS_CXX17
5963
#endif

include/internal/csv_reader.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,11 @@ namespace csv {
8282

8383
/** Access the CSVRow held by the iterator */
8484
CONSTEXPR_14 reference operator*() { return this->row; }
85+
CONSTEXPR_14 reference operator*() const { return const_cast<reference>(this->row); }
8586

8687
/** Return a pointer to the CSVRow the iterator has stopped at */
8788
CONSTEXPR_14 pointer operator->() { return &(this->row); }
89+
CONSTEXPR_14 pointer operator->() const { return const_cast<pointer>(&(this->row)); }
8890

8991
iterator& operator++(); /**< Pre-increment iterator */
9092
iterator operator++(int); /**< Post-increment iterator */

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ target_sources(csv_test
2727
test_data_type.cpp
2828
test_raw_csv_data.cpp
2929
test_round_trip.cpp
30+
test_csv_ranges.cpp
3031
)
3132
target_link_libraries(csv_test csv)
3233
target_link_libraries(csv_test Catch2::Catch2WithMain)

tests/test_csv_ranges.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#include <catch2/catch_all.hpp>
2+
#include <csv.hpp>
3+
4+
#ifdef CSV_HAS_CXX20
5+
#include <ranges>
6+
7+
TEST_CASE("CSVReader C++20 Ranges Compatibility", "[ranges][cxx20]") {
8+
SECTION("CSVReader works with std::ranges::distance") {
9+
std::stringstream ss("A,B,C\n1,2,3\n4,5,6\n7,8,9");
10+
csv::CSVReader reader(ss);
11+
12+
auto count = std::ranges::distance(reader);
13+
REQUIRE(count == 3);
14+
}
15+
16+
SECTION("CSVReader works with std::views") {
17+
std::stringstream ss("A,B,C\n1,2,3\n4,5,6\n7,8,9\n10,11,12");
18+
csv::CSVReader reader(ss);
19+
20+
auto filtered = reader |
21+
std::views::filter([](const csv::CSVRow &row) {
22+
return !row.empty() && row[0].get<int>() > 5;
23+
});
24+
25+
int filtered_count = 0;
26+
for (const auto &row : filtered) {
27+
filtered_count++;
28+
int val = row[0].get<int>();
29+
REQUIRE(val > 5);
30+
}
31+
REQUIRE(filtered_count == 2); // rows with 7 and 10
32+
}
33+
34+
SECTION("CSVReader iterator satisfies input_range requirements") {
35+
std::stringstream ss("A,B\n1,2\n3,4");
36+
csv::CSVReader reader(ss);
37+
38+
auto it = reader.begin();
39+
auto end = reader.end();
40+
41+
static_assert(std::input_iterator<decltype(it)>);
42+
static_assert(std::ranges::range<csv::CSVReader>);
43+
static_assert(std::ranges::input_range<csv::CSVReader>);
44+
static_assert(std::sentinel_for<decltype(end), decltype(it)>);
45+
46+
REQUIRE(it != end);
47+
auto row = *it;
48+
REQUIRE(row.size() == 2);
49+
50+
++it;
51+
REQUIRE(it != end);
52+
53+
++it;
54+
REQUIRE(it == end);
55+
}
56+
}
57+
#endif

0 commit comments

Comments
 (0)