Skip to content

Commit 72d059a

Browse files
Add errors.reserve to help the compiler
1 parent acec4c5 commit 72d059a

7 files changed

Lines changed: 40 additions & 54 deletions

File tree

docs/supported_formats/cereal.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ Furthermore, when compiling reflect-cpp, you need to pass `-DREFLECTCPP_CEREAL=O
55

66
Cereal is a C++ serialization library that provides multiple archive formats including binary, portable binary, JSON, and XML formats, even though we use the portable binary format.
77

8-
Note that on some versions of GCC, it is necessary to compile with `-Wno-stringop-overflow`, because of false positive warnings due to a known compiler bug, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110498.
9-
108
## Reading and writing
119

1210
Suppose you have a struct like this:

include/rfl/parsing/NamedTupleParser.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -262,10 +262,8 @@ struct NamedTupleParser {
262262
if constexpr (is_required_field) {
263263
constexpr auto current_name =
264264
internal::nth_element_t<_i, FieldTypes...>::name();
265-
std::stringstream stream;
266-
stream << "Field named '" << std::string(current_name)
267-
<< "' not found.";
268-
_errors->emplace_back(stream.str());
265+
_errors->emplace_back("Field named '" + std::string(current_name) +
266+
"' not found.");
269267

270268
} else if constexpr (!internal::has_default_val_v<NamedTupleType>) {
271269
if constexpr (!std::is_const_v<ValueType>) {
@@ -306,6 +304,7 @@ struct NamedTupleParser {
306304
auto set = std::array<bool, NamedTupleType::size()>();
307305
set.fill(false);
308306
std::vector<std::string> errors;
307+
errors.reserve(size_);
309308
const auto reader = ViewReaderType(&_r, _view, &found, &set, &errors);
310309
if constexpr (_no_field_names) {
311310
const auto err = _r.read_array(reader, _obj_or_arr);
@@ -330,6 +329,7 @@ struct NamedTupleParser {
330329
const R& _r, const InputObjectOrArrayType& _obj_or_arr,
331330
NamedTupleType* _view) noexcept {
332331
std::vector<std::string> errors;
332+
errors.reserve(size_);
333333
const auto reader = ViewReaderWithDefaultType(&_r, _view, &errors);
334334
if constexpr (_no_field_names) {
335335
const auto err = _r.read_array(reader, _obj_or_arr);

include/rfl/parsing/ViewReader.hpp

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,8 @@ class ViewReader {
7474
auto res = Parser<R, W, T, ProcessorsType>::read(_r, _var);
7575
if (!res) {
7676
constexpr auto name = FieldType::name();
77-
std::stringstream stream;
78-
stream << "Failed to parse field '" << name
79-
<< "': " << res.error().what();
80-
_errors->emplace_back(stream.str());
77+
_errors->emplace_back("Failed to parse field '" + std::string(name) +
78+
"': " + res.error().what());
8179
return;
8280
}
8381
if constexpr (std::is_pointer_v<OriginalType>) {
@@ -106,10 +104,9 @@ class ViewReader {
106104
}
107105
auto res = Parser<R, W, T, ProcessorsType>::read(_r, _var);
108106
if (!res) {
109-
std::stringstream stream;
110-
stream << "Failed to parse field '" << _current_name
111-
<< "': " << res.error().what();
112-
_errors->emplace_back(stream.str());
107+
_errors->emplace_back("Failed to parse field '" +
108+
std::string(_current_name) +
109+
"': " + res.error().what());
113110
return;
114111
}
115112
extra_fields->emplace(std::string(_current_name), std::move(*res));
@@ -142,13 +139,22 @@ class ViewReader {
142139
"Passing rfl::NoExtraFields to a schemaful format does not make "
143140
"sense, because schemaful formats cannot have extra fields.");
144141
if (!already_assigned) {
145-
std::stringstream stream;
146-
stream << "Value named '" << _current_name_or_index << "' not used.";
147-
_errors->emplace_back(stream.str());
142+
_errors->emplace_back("Value named '" +
143+
to_string(_current_name_or_index) +
144+
"' not used.");
148145
}
149146
}
150147
}
151148

149+
template <class T>
150+
static std::string to_string(const T& _v) {
151+
if constexpr (std::is_integral_v<std::remove_cvref_t<T>>) {
152+
return std::to_string(_v);
153+
} else {
154+
return std::string(_v);
155+
}
156+
}
157+
152158
template <class Target, class Source>
153159
static void move_to(Target* _t, Source* _s) {
154160
if constexpr (std::is_const_v<Target>) {

include/rfl/parsing/ViewReaderWithDefault.hpp

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,8 @@ class ViewReaderWithDefault {
6060
*_already_assigned = true;
6161
auto res = Parser<R, W, T, ProcessorsType>::read(_r, _var);
6262
if (!res) {
63-
std::stringstream stream;
64-
stream << "Failed to parse field '" << std::string(name)
65-
<< "': " << res.error().what();
66-
_errors->emplace_back(stream.str());
63+
_errors->emplace_back("Failed to parse field '" + std::string(name) +
64+
"': " + res.error().what());
6765
return;
6866
}
6967
if constexpr (std::is_pointer_v<OriginalType>) {
@@ -86,10 +84,9 @@ class ViewReaderWithDefault {
8684
std::remove_pointer_t<typename ExtraFieldsType::Type>>;
8785
auto res = Parser<R, W, T, ProcessorsType>::read(_r, _var);
8886
if (!res) {
89-
std::stringstream stream;
90-
stream << "Failed to parse field '" << _current_name
91-
<< "': " << res.error().what();
92-
_errors->emplace_back(stream.str());
87+
_errors->emplace_back("Failed to parse field '" +
88+
std::string(_current_name) +
89+
"': " + res.error().what());
9390
return;
9491
}
9592
extra_fields->emplace(std::string(_current_name), std::move(*res));
@@ -114,11 +111,10 @@ class ViewReaderWithDefault {
114111
}
115112
} else if constexpr (ProcessorsType::no_extra_fields_) {
116113
if (!already_assigned) {
117-
std::stringstream stream;
118-
stream << "Value named '" << std::string(_current_name)
119-
<< "' not used. Remove the rfl::NoExtraFields processor or add "
120-
"rfl::ExtraFields to avoid this error message.";
121-
_errors->emplace_back(stream.str());
114+
_errors->emplace_back(
115+
"Value named '" + std::string(_current_name) +
116+
"' not used. Remove the rfl::NoExtraFields processor or add "
117+
"rfl::ExtraFields to avoid this error message.");
122118
}
123119
}
124120
}

include/rfl/parsing/ViewReaderWithDefaultAndStrippedFieldNames.hpp

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,8 @@ class ViewReaderWithDefaultAndStrippedFieldNames {
3838
/// used when the field names are stripped.
3939
std::optional<Error> read(const InputVarType& _var) const {
4040
if (i_ == size_) {
41-
std::stringstream stream;
42-
stream << "Expected a maximum of " << std::to_string(size_)
43-
<< " fields, but got at least one more.";
44-
return Error(stream.str());
41+
return Error("Expected a maximum of " + std::to_string(size_) +
42+
" fields, but got at least one more.");
4543
}
4644
assign_to_field_i(*r_, _var, view_, errors_, i_,
4745
std::make_integer_sequence<int, size_>());
@@ -63,13 +61,10 @@ class ViewReaderWithDefaultAndStrippedFieldNames {
6361
if (_i == i) {
6462
auto res = Parser<R, W, T, ProcessorsType>::read(_r, _var);
6563
if (!res) {
66-
std::stringstream stream;
67-
stream << "Failed to parse field '" << std::string(name)
68-
<< "': " << res.error().what();
69-
_errors->emplace_back(stream.str());
64+
_errors->emplace_back("Failed to parse field '" + std::string(name) +
65+
"': " + res.error().what());
7066
return;
71-
}
72-
if constexpr (std::is_pointer_v<OriginalType>) {
67+
} if constexpr (std::is_pointer_v<OriginalType>) {
7368
move_to(rfl::get<i>(*_view), &(*res));
7469
} else {
7570
rfl::get<i>(*_view) = std::move(*res);

include/rfl/parsing/ViewReaderWithStrippedFieldNames.hpp

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,8 @@ class ViewReaderWithStrippedFieldNames {
3939
/// used when the field names are stripped.
4040
std::optional<Error> read(const InputVarType& _var) const {
4141
if (i_ == size_) {
42-
std::stringstream stream;
43-
stream << "Expected a maximum of " << std::to_string(size_)
44-
<< " fields, but got at least one more.";
45-
return Error(stream.str());
42+
return Error("Expected a maximum of " + std::to_string(size_) +
43+
" fields, but got at least one more.");
4644
}
4745
assign_to_field_i(*r_, _var, view_, errors_, found_, set_, i_,
4846
std::make_integer_sequence<int, size_>());
@@ -66,13 +64,10 @@ class ViewReaderWithStrippedFieldNames {
6664
std::get<i>(*_found) = true;
6765
auto res = Parser<R, W, T, ProcessorsType>::read(_r, _var);
6866
if (!res) {
69-
std::stringstream stream;
70-
stream << "Failed to parse field '" << std::string(name)
71-
<< "': " << res.error().what();
72-
_errors->emplace_back(stream.str());
67+
_errors->emplace_back("Failed to parse field '" + std::string(name) +
68+
"': " + res.error().what());
7369
return;
74-
}
75-
if constexpr (std::is_pointer_v<OriginalType>) {
70+
} if constexpr (std::is_pointer_v<OriginalType>) {
7671
move_to(rfl::get<i>(*_view), &(*res));
7772
} else {
7873
rfl::get<i>(*_view) = std::move(*res);

tests/cereal/CMakeLists.txt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@ add_executable(
88
)
99
target_precompile_headers(reflect-cpp-cereal-tests PRIVATE [["rfl.hpp"]] <iostream> <string> <functional> <gtest/gtest.h>)
1010

11-
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
12-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-stringop-overflow")
13-
endif()
14-
1511
target_link_libraries(reflect-cpp-cereal-tests PRIVATE reflectcpp_tests_crt)
1612

1713
add_custom_command(TARGET reflect-cpp-cereal-tests POST_BUILD

0 commit comments

Comments
 (0)