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
+6 -6
View File
@@ -312,7 +312,7 @@ class Contractor
tbb::parallel_for(tbb::blocked_range<int>(0, number_of_nodes, InitGrainSize),
[&remaining_nodes](const tbb::blocked_range<int> &range)
{
for (int x = range.begin(); x != range.end(); ++x)
for (int x = range.begin(), end = range.end(); x != end; ++x)
{
remaining_nodes[x].id = x;
}
@@ -324,7 +324,7 @@ class Contractor
const tbb::blocked_range<int> &range)
{
ContractorThreadData *data = thread_data_list.getThreadData();
for (int x = range.begin(); x != range.end(); ++x)
for (int x = range.begin(), end = range.end(); x != end; ++x)
{
node_priorities[x] =
this->EvaluateNodePriority(data, &node_data[x], x);
@@ -430,7 +430,7 @@ class Contractor
{
ContractorThreadData *data = thread_data_list.getThreadData();
// determine independent node set
for (int i = range.begin(); i != range.end(); ++i)
for (int i = range.begin(), end = range.end(); i != end; ++i)
{
const NodeID node = remaining_nodes[i].id;
remaining_nodes[i].is_independent =
@@ -451,7 +451,7 @@ class Contractor
[this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int> &range)
{
ContractorThreadData *data = thread_data_list.getThreadData();
for (int position = range.begin(); position != range.end(); ++position)
for (int position = range.begin(), end = range.end(); position != end; ++position)
{
const NodeID x = remaining_nodes[position].id;
this->ContractNode<false>(data, x);
@@ -470,7 +470,7 @@ class Contractor
[this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int> &range)
{
ContractorThreadData *data = thread_data_list.getThreadData();
for (int position = range.begin(); position != range.end(); ++position)
for (int position = range.begin(), end = range.end(); position != end; ++position)
{
const NodeID x = remaining_nodes[position].id;
this->DeleteIncomingEdges(data, x);
@@ -508,7 +508,7 @@ class Contractor
const tbb::blocked_range<int> &range)
{
ContractorThreadData *data = thread_data_list.getThreadData();
for (int position = range.begin(); position != range.end(); ++position)
for (int position = range.begin(), end = range.end(); position != end; ++position)
{
NodeID x = remaining_nodes[position].id;
this->UpdateNodeNeighbours(node_priorities, node_data, data, x);