Skip to content

Commit c5a53b6

Browse files
authored
Add inplace vector support (#733)
1 parent 320f780 commit c5a53b6

5 files changed

Lines changed: 91 additions & 1 deletion

File tree

‎README.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,7 @@ reflect-cpp supports the following containers from the C++ standard library:
621621
- `std::chrono::duration`
622622
- `std::filesystem::path`
623623
- `std::forward_list`
624+
- `std::inplace_vector` (C++26)
624625
- `std::map`
625626
- `std::multimap`
626627
- `std::multiset`

‎include/rfl/parsing/VectorReader.hpp‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
#define RFL_PARSING_VECTORREADER_HPP_
33

44
#include <optional>
5+
#include <string>
56
#include <type_traits>
67

78
#include "../Result.hpp"
89
#include "Parser_base.hpp"
10+
#include "is_inplace_vector.hpp"
911
#include "is_map_like.hpp"
1012
#include "is_set_like.hpp"
1113

@@ -47,14 +49,19 @@ class VectorReader {
4749
const auto insert = [this](auto&& _var) -> std::optional<Error> {
4850
if constexpr (is_map_like_v<VecType> || is_set_like_v<VecType>) {
4951
vec_->insert(std::move(_var));
52+
} else if constexpr (is_inplace_vector_v<VecType>) {
53+
if (!vec_->try_emplace_back(std::move(_var))) {
54+
return Error("Too many elements, capacity is " +
55+
std::to_string(vec_->capacity()) + ".");
56+
}
5057
} else {
5158
vec_->emplace_back(std::move(_var));
5259
}
5360
return std::nullopt;
5461
};
5562
auto res = parse(_var).transform(insert);
5663
if (res) {
57-
return std::nullopt;
64+
return *res;
5865
} else {
5966
return res.error();
6067
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#ifndef RFL_PARSING_IS_INPLACE_VECTOR_HPP_
2+
#define RFL_PARSING_IS_INPLACE_VECTOR_HPP_
3+
4+
#include <cstddef>
5+
#include <type_traits>
6+
7+
#if __has_include(<inplace_vector>)
8+
#include <inplace_vector>
9+
#endif
10+
11+
namespace rfl {
12+
namespace parsing {
13+
14+
/**
15+
* @brief Trait to check if a type is a std::inplace_vector.
16+
*
17+
* @tparam T The type to check.
18+
*/
19+
template <class T>
20+
class is_inplace_vector;
21+
22+
template <class T>
23+
class is_inplace_vector : public std::false_type {};
24+
25+
#if defined(__cpp_lib_inplace_vector)
26+
template <class T, std::size_t N>
27+
class is_inplace_vector<std::inplace_vector<T, N>> : public std::true_type {};
28+
#endif // __cpp_lib_inplace_vector
29+
30+
template <class T>
31+
constexpr bool is_inplace_vector_v =
32+
is_inplace_vector<std::remove_cvref_t<T>>::value;
33+
34+
} // namespace parsing
35+
} // namespace rfl
36+
37+
#endif

‎include/rfl/parsing/is_vector_like.hpp‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#include <unordered_set>
1111
#include <vector>
1212

13+
#include "is_inplace_vector.hpp"
14+
1315
namespace rfl::parsing {
1416

1517
/**
@@ -67,6 +69,11 @@ class is_vector_like<std::unordered_set<T, Hash, KeyEqual, Allocator>>
6769
template <class T>
6870
class is_vector_like<std::vector<T>> : public std::true_type {};
6971

72+
#if defined(__cpp_lib_inplace_vector)
73+
template <class T, std::size_t N>
74+
class is_vector_like<std::inplace_vector<T, N>> : public std::true_type {};
75+
#endif // __cpp_lib_inplace_vector
76+
7077
template <class T>
7178
constexpr bool is_vector_like_v = is_vector_like<std::remove_cvref_t<T>>::value;
7279

‎tests/json/test_inplace_vector.cpp‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#include <rfl.hpp>
2+
#include <rfl/json.hpp>
3+
#include <string>
4+
5+
#include "write_and_read.hpp"
6+
7+
#if __has_include(<inplace_vector>)
8+
#include <inplace_vector>
9+
#endif
10+
11+
#if defined(__cpp_lib_inplace_vector)
12+
13+
namespace test_inplace_vector {
14+
15+
struct Person {
16+
rfl::Rename<"firstName", std::string> first_name;
17+
rfl::Rename<"lastName", std::string> last_name = "Simpson";
18+
std::inplace_vector<std::string, 3> children;
19+
};
20+
21+
TEST(json, test_inplace_vector) {
22+
const auto homer =
23+
Person{.first_name = "Homer", .children = {"Bart", "Lisa", "Maggie"}};
24+
25+
write_and_read(
26+
homer,
27+
R"({"firstName":"Homer","lastName":"Simpson","children":["Bart","Lisa","Maggie"]})");
28+
}
29+
30+
TEST(json, test_inplace_vector_overflow) {
31+
const auto res = rfl::json::read<Person>(
32+
R"({"firstName":"Homer","children":["Bart","Lisa","Maggie","Hugo"]})");
33+
EXPECT_FALSE(res && true);
34+
}
35+
36+
} // namespace test_inplace_vector
37+
38+
#endif // __cpp_lib_inplace_vector

0 commit comments

Comments
 (0)