Caches iterators instead of invoking function calls on every iteration.

This caches iterators, i.e. especially the end iterator when possible.

The problem:

    for (auto it = begin(seq); it != end(seq); ++it)

this has to call `end(seq)` on every iteration, since the compiler is
not able to reason about the call's site effects (to bad, huh).

Instead do it like this:

    for (auto it = begin(seq), end = end(seq); it != end; ++it)

caching the end iterator.

Of course, still better would be:

    for (auto&& each : seq)

if all you want is value semantics.

Why `auto&&` you may ask? Because it binds to everything and never copies!

Skim the referenced proposal (that was rejected, but nevertheless) for a
detailed explanation on range-based for loops and why `auto&&` is great.

Reference:

- http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3853.htm
This commit is contained in:
Daniel J. Hofmann
2015-09-15 01:13:31 +02:00
parent 8e02263084
commit 94af9b7f13
7 changed files with 66 additions and 56 deletions
+14 -20
View File
@@ -61,12 +61,11 @@ struct Renderer : mapbox::util::static_visitor<>
void operator()(const Object &object) const
{
out << "{";
auto iterator = object.values.begin();
while (iterator != object.values.end())
for (auto it = object.values.begin(), end = object.values.end(); it != end;)
{
out << "\"" << (*iterator).first << "\":";
mapbox::util::apply_visitor(Renderer(out), (*iterator).second);
if (++iterator != object.values.end())
out << "\"" << it->first << "\":";
mapbox::util::apply_visitor(Renderer(out), it->second);
if (++it != end)
{
out << ",";
}
@@ -77,12 +76,10 @@ struct Renderer : mapbox::util::static_visitor<>
void operator()(const Array &array) const
{
out << "[";
std::vector<Value>::const_iterator iterator;
iterator = array.values.begin();
while (iterator != array.values.end())
for (auto it = array.values.cend(), end = array.values.cend(); it != end;)
{
mapbox::util::apply_visitor(Renderer(out), *iterator);
if (++iterator != array.values.end())
mapbox::util::apply_visitor(Renderer(out), *it);
if (++it != end)
{
out << ",";
}
@@ -121,16 +118,15 @@ struct ArrayRenderer : mapbox::util::static_visitor<>
void operator()(const Object &object) const
{
out.push_back('{');
auto iterator = object.values.begin();
while (iterator != object.values.end())
for (auto it = object.values.begin(), end = object.values.end(); it != end;)
{
out.push_back('\"');
out.insert(out.end(), (*iterator).first.begin(), (*iterator).first.end());
out.insert(out.end(), it->first.begin(), it->first.end());
out.push_back('\"');
out.push_back(':');
mapbox::util::apply_visitor(ArrayRenderer(out), (*iterator).second);
if (++iterator != object.values.end())
mapbox::util::apply_visitor(ArrayRenderer(out), it->second);
if (++it != end)
{
out.push_back(',');
}
@@ -141,12 +137,10 @@ struct ArrayRenderer : mapbox::util::static_visitor<>
void operator()(const Array &array) const
{
out.push_back('[');
std::vector<Value>::const_iterator iterator;
iterator = array.values.begin();
while (iterator != array.values.end())
for (auto it = array.values.cbegin(), end = array.values.cend(); it != end;)
{
mapbox::util::apply_visitor(ArrayRenderer(out), *iterator);
if (++iterator != array.values.end())
mapbox::util::apply_visitor(ArrayRenderer(out), *it);
if (++it != end)
{
out.push_back(',');
}
+2 -1
View File
@@ -132,9 +132,10 @@ inline std::string escape_JSON(const std::string &input)
inline std::size_t URIDecode(const std::string &input, std::string &output)
{
auto src_iter = std::begin(input);
const auto src_end = std::end(input);
output.resize(input.size() + 1);
std::size_t decoded_length = 0;
for (decoded_length = 0; src_iter != std::end(input); ++decoded_length)
for (decoded_length = 0; src_iter != src_end; ++decoded_length)
{
if (src_iter[0] == '%' && src_iter[1] && src_iter[2] && isxdigit(src_iter[1]) &&
isxdigit(src_iter[2]))
+8 -13
View File
@@ -56,38 +56,33 @@ struct XMLToArrayRenderer : mapbox::util::static_visitor<>
void operator()(const Object &object) const
{
auto iterator = object.values.begin();
while (iterator != object.values.end())
for (auto &&each : object.values)
{
if (iterator->first.at(0) != '_')
if (each.first.at(0) != '_')
{
out.push_back('<');
out.insert(out.end(), (*iterator).first.begin(), (*iterator).first.end());
out.insert(out.end(), each.first.begin(), each.first.end());
}
else
{
out.push_back(' ');
out.insert(out.end(), ++(*iterator).first.begin(), (*iterator).first.end());
out.insert(out.end(), ++(each).first.begin(), each.first.end());
out.push_back('=');
}
mapbox::util::apply_visitor(XMLToArrayRenderer(out), (*iterator).second);
if (iterator->first.at(0) != '_')
mapbox::util::apply_visitor(XMLToArrayRenderer(out), each.second);
if (each.first.at(0) != '_')
{
out.push_back('/');
out.push_back('>');
}
++iterator;
}
}
void operator()(const Array &array) const
{
std::vector<Value>::const_iterator iterator;
iterator = array.values.begin();
while (iterator != array.values.end())
for (auto &&each : array.values)
{
mapbox::util::apply_visitor(XMLToArrayRenderer(out), *iterator);
++iterator;
mapbox::util::apply_visitor(XMLToArrayRenderer(out), each);
}
}