Code 1:
#include <iostream>
#include <vector>
class Vector2d {
public:
double x, y;
Vector2d(double x, double y) : x(x), y(y) { }
};
int main() {
const double FoV = 50.0;
std::vector<Vector2d> vecOfVector2d;
vecOfVector2d.emplace_back(Vector2d(2.0, 3.0));
vecOfVector2d.emplace_back(Vector2d(4.0, 5.0));
for (std::vector<Vector2d>::const_iterator i = vecOfVector2d.begin(); i != vecOfVector2d.end(); ++i) {
const Vector2d vec = *i;
double xpos = rand() % 100; // Calculated but varies in each iteration
auto isBBoxInsideFOVHorizontal = [FoV, xpos, vec]()->bool{
std::cout << xpos << " " << vec.x << " " << vec.y << std::endl;
return true;
};
isBBoxInsideFOVHorizontal();
}
return 0;
}
Code 2:
#include <iostream>
#include <vector>
class Vector2d {
public:
double x, y;
Vector2d(double x, double y) : x(x), y(y) { }
};
int main() {
const double FoV = 50.0;
std::vector<Vector2d> vecOfVector2d;
vecOfVector2d.emplace_back(Vector2d(2.0, 3.0));
vecOfVector2d.emplace_back(Vector2d(4.0, 5.0));
auto isBBoxInsideFOVHorizontal = [FoV](const double xpos, const Vector2d vec)->bool{
std::cout << xpos << " " << vec.x << " " << vec.y << std::endl;
return true;
};
for (std::vector<Vector2d>::const_iterator i = vecOfVector2d.begin(); i != vecOfVector2d.end(); ++i) {
const Vector2d vec = *i;
double xpos = rand() % 100; // Calculated but varies in each iteration
isBBoxInsideFOVHorizontal(xpos, vec);
}
return 0;
}
Code 3:
#include <iostream>
#include <vector>
class Vector2d {
public:
double x, y;
Vector2d(double x, double y) : x(x), y(y) { }
};
int main() {
const double FoV = 50.0;
std::vector<Vector2d> vecOfVector2d;
vecOfVector2d.emplace_back(Vector2d(2.0, 3.0));
vecOfVector2d.emplace_back(Vector2d(4.0, 5.0));
for (std::vector<Vector2d>::const_iterator i = vecOfVector2d.begin(); i != vecOfVector2d.end(); ++i) {
const Vector2d vec = *i;
double xpos = rand() % 100; // Calculated but varies in each iteration
auto isBBoxInsideFOVHorizontal = [FoV](const double xpos, const Vector2d vec)->bool{
std::cout << xpos << " " << vec.x << " " << vec.y << std::endl;
return true;
};
isBBoxInsideFOVHorizontal(xpos, vec);
}
return 0;
}
All 3 versions work. Although, this piece of code (local function) should be kept inside the for loop where it belongs conceptually. The for loop is really long and putting this small local function thousands of lines above should be avoided in this case.
Could someone explain clearly if Code 1 (and 3) create multiple structures or has any kind of additional computational burden? Especially in the case of Code 3, keeping FoV
(that never changes) in the capture list creates any problem (such as multiple creation of functors)?
OR Codes 1, 2 and 3 are 100% equivalent in compilation/execution terms (of course bear in mind this is just a MWE for discussion and so that you can compile it, actual structures might differ)?
8
In both of these examples, you’re executing the functor immediately inside the loop, and never anywhere else. In such a case, both versions are essentially equivalent, and you can use whichever you want.
Version 2 is no different from defining a normal function and executing it inside the loop. In fact, if you’re just trying to clean up your code, I’d recommend just implementing a separate function or private method within the enclosing class – it may not appear as clean at first, as it’ll separate the code, but it’ll help with maintainability in the long run, as it leads to smaller functions with more isolated and well defined effects.
Version 1 is worth special attention in a more general case because of its ability to capture values. This is equivalent to binding arguments to a function. This is especially useful if you wish for a delayed execution of the function at a later point in time, rather than executing that logic within the loop immediately after it’s defined.
As an example, I modified your code to show this specific use case:
class Vector2d {
public:
double x, y;
Vector2d(double x, double y) : x(x), y(y) { }
};
int main() {
const double FoV = 50.0;
std::vector<Vector2d> vecOfVector2d;
vecOfVector2d.emplace_back(Vector2d(2.0, 3.0));
vecOfVector2d.emplace_back(Vector2d(4.0, 5.0));
vecOfVector2d.emplace_back(Vector2d(6.0, 7.0));
vecOfVector2d.emplace_back(Vector2d(8.0, 9.0));
std::vector<std::function<bool()>> vecOfFunctors; // Store the functors for execution at a later point in time.
for (std::vector<Vector2d>::const_iterator i = vecOfVector2d.begin(); i != vecOfVector2d.end(); ++i) {
const Vector2d vec = *i;
double xpos = rand() % 100; // Calculated but varies in each iteration
std::function<bool()> isBBoxInsideFOVHorizontal = [FoV, xpos, vec]()->bool {
std::cout << FoV << " " << xpos << " " << vec.x << " " << vec.y << std::endl;
return true;
};
vecOfFunctors.push_back(isBBoxInsideFOVHorizontal);
isBBoxInsideFOVHorizontal();
}
// This loop shows a delayed execution of the previously declared
for (const auto& func : vecOfFunctors)
{
func();
}
return 0;
}
4