Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use structured bindings #2322

Merged
merged 15 commits into from
Sep 2, 2019
Merged

Conversation

eggrobin
Copy link
Member

@eggrobin eggrobin commented Sep 2, 2019

Iteration on maps

This changes most instances of

for (auto const& pair : ⟨map⟩)

to

for (auto const& [key, value] : ⟨map⟩)

The exceptions are

for (auto const& pair : name_to_degrees_of_freedom) {
degrees_of_freedom.push_back(pair.second);
}

where the name degrees_of_freedom is taken,
and the public functions of the journal proto processor:
std::vector<std::string>
JournalProtoProcessor::GetCsInterfaceMethodDeclarations() const {
std::vector<std::string> result;
for (auto const& pair : cs_interface_method_declaration_) {
result.push_back(pair.second);
}
return result;
}
std::vector<std::string>
JournalProtoProcessor::GetCsInterfaceTypeDeclarations() const {
std::vector<std::string> result;
for (auto const& pair : cs_interface_type_declaration_) {
result.push_back(pair.second);
}
return result;
}
std::vector<std::string>
JournalProtoProcessor::GetCxxInterfaceMethodDeclarations() const {
std::vector<std::string> result;
for (auto const& pair : cxx_interface_method_declaration_) {
result.push_back(pair.second);
}
return result;
}
std::vector<std::string>
JournalProtoProcessor::GetCxxInterfaceTypeDeclarations() const {
std::vector<std::string> result;
for (auto const& pair : cxx_interface_type_declaration_) {
result.push_back(pair.second);
}
return result;
}
std::vector<std::string>
JournalProtoProcessor::GetCxxInterchangeImplementations() const {
std::vector<std::string> result;
result.push_back("namespace {\n\n");
for (auto const& pair : cxx_deserialize_definition_) {
result.push_back(pair.second);
}
for (auto const& pair : cxx_serialize_definition_) {
result.push_back(pair.second);
}
result.push_back("} // namespace\n\n");
return result;
}
std::vector<std::string>
JournalProtoProcessor::GetCxxMethodImplementations() const {
std::vector<std::string> result;
for (auto const& pair : cxx_functions_implementation_) {
result.push_back(pair.second);
}
return result;
}
std::vector<std::string> JournalProtoProcessor::GetCxxMethodTypes() const {
std::vector<std::string> result;
for (auto const& pair : cxx_toplevel_type_declaration_) {
result.push_back(pair.second);
}
return result;
}
std::vector<std::string> JournalProtoProcessor::GetCxxPlayStatements() const {
std::vector<std::string> result;
result.push_back("{\n bool ran = false;\n");
for (auto const& pair : cxx_play_statement_) {
result.push_back(pair.second);
}
result.push_back(" CHECK(ran) << method_in->DebugString() << \"\\n\"\n"
" << method_out_return->DebugString();\n}\n");
return result;
}

In both cases, switching to structured bindings felt clumsier than the existing code. It is noteworthy that both are examples of the same pattern, turning the values of a map into a vector; perhaps we could write an utility function for that.

_ for unused keys

Where the key is unused, this pull request uses

for (auto const& [_, value] : ⟨map⟩)

In the future, we will probably want to introduce an iterator adapter ValuesIn and change these usages to

for (auto const& value : ValuesIn(⟨map⟩))

Iterator adapters would also make it possible to turn usages of Vessel::ForAllParts into actual loops.

insert and emplace

use bool const inserted = ⟨container⟩.insert(...).second if only the boolean is used, reusing an existing bool inserted if there are scoping issues; use structured bindings if both are used (where previously either std::tie or references into the pair would be used).

One usage of std::tie remains, which is a proper tie of pre-existing variables:

void Plugin::InsertOrKeepVessel(GUID const& vessel_guid,
std::string const& vessel_name,
Index const parent_index,
bool const loaded,
bool& inserted) {
CHECK(!initializing_);
not_null<Celestial const*> parent =
FindOrDie(celestials_, parent_index).get();
auto it = vessels_.find(vessel_guid);
if (it == vessels_.end()) {
std::tie(it, inserted) =
vessels_.emplace(
vessel_guid,
make_not_null_unique<Vessel>(vessel_guid,
vessel_name,
parent,
ephemeris_.get(),
DefaultPredictionParameters()));
} else {
inserted = false;
}
not_null<Vessel*> const vessel = it->second.get();

Note that in the future, we should probably change LOG_IF in our glog fork to use if rather than ?:, so that it is possible to narrowly scope inserted, thus

CHECK(bool const inserted = container.insert(...).second; inserted) << ...;

Copy link
Member

@pleroy pleroy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR could/should also fix all usage of std::tie.

@@ -180,8 +180,8 @@ serialization::OblateBody::Geopotential MakeGeopotential(
}

serialization::OblateBody::Geopotential result;
for (auto const& pair : rows) {
*result.add_row() = pair.second;
for (auto const& [degree, row] : rows) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am wondering if we should write:

for (auto const& [_, row] : rows) {

in the case where one of the elements is not used. That would maybe make the code more readable (otherwise I am left wondering where degree is used).

@eggrobin eggrobin changed the title Use structured bindings when iterating on maps Use structured bindings Sep 2, 2019
@pleroy pleroy added the LGTM label Sep 2, 2019
@eggrobin eggrobin merged commit 31f2c60 into mockingbirdnest:master Sep 2, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants