Better design for using function pointers with varying arguments - c++

I have an optimisation algorithm which finds the best partition of a graph.
There are many measures for the quality of a partition (the variable being optimised), so I thought it would be a good idea to use function pointers to these quality functions, and pass that into my optimisation algorithm function.
This works fine, but the problem is different quality functions take some different arguments.
For example one quality function is find_linearised_stability and it requires a markov_time parameter:
float find_linearised_stability(cliques::Graph<T> &my_graph, cliques::Partition &my_partition,
std::vector<float> &markov_times, std::vector<float> &stabilities)
and is used in the optimisation function :
cliques::find_optimal_partition_louvain(my_new_graph, markov_times, &cliques::find_linearised_stability);
however another quality function find_modularityrequires no markov_time parameter. Of course I could just include it as an argument and not use it in the function but that seems like bad practice, and would get unwieldy once I start adding a lot of different quality functions.
What is a better design for this kind of situation?

Use function objects. One of those function objects can have a markov_time member that is passed in to the constructor:
struct find_linearised_stability {
std::vector<float> & markov_times_;
find_linearised_stability(std::vector<float> & markov_times)
:markov_times_(markov_times)
{}
float operator () (cliques::Graph<T> &my_graph, cliques::Partition &my_partition,
std::vector<float> &stabilities)
{
// use markov_times_ in here, we didn't need to pass it since it's a member
}
};
(you may need to make adjustments to constness/referenceness to suit your needs)
Then you can call your function like this:
cliques::find_optimal_partition_louvain(my_new_graph, cliques::find_linearised_stability(markov_times));
"what type for the function object do I use when declaring the ... function?"
Make it a function template that takes the function object type as a template parameter, thusly:
template<typename PR>
whatever find_optimal_partition_louvain(my_new_graph, PR & pr)
{
...
pr(my_new_graph, partition, stabilities);
...
}

Your only option is boost::bind or something like it stored in a boost::function or something like it.
If profiling shows that to be too slow then you'll be stuck with the "poor practice" version because any alternative is going to run afoul of UB and/or end up being just as 'slow' as the more reasonable alternative.

parameter is not known before: add argument to every function (reference/pointer) that contains all info, every function uses whatever it needs
parameter is known before: use boost::bind, e.g.:
sample source code:
#include <iostream>
#include <cstddef>
#include <algorithm>
#include <boost/bind.hpp>
using namespace std;
void output(int a, int b)
{
cout << a << ", " << b << '\n';
}
int main()
{
int arr[] = { 1, 2, 3, 4, 5 };
for_each(arr, arr + 5, bind(output, 5, _1));
return 0;
}
Outputs:
5, 1
5, 2
5, 3
5, 4
5, 5

Related

Passing a pointer for a dynamic runtime function

I'm trying to write a generic utility function for a class that applies a function to each element of a vector with the only input argument being the value of that element. The idea being that I can use that to support scalar addition/multiplication as well as user-specified functions without duplicating too much code. It works fine for the user-specified functions, but I'm struggling with how the best implement it for scalar addition/multiplication.
The code below is a simplified version of what I'm playing around with. It works fine, but what I want to be able to do is have the "5" in the lambda expression be a variable passed in separately, but not necessarily passed into "apply_f". So keep apply_f only taking a vector an a function pointer. I'm aware of the captures field for lambda expressions, but I was having trouble passing a lambda function with a capture into another function. I'm also aware of something like std::bind, but couldn't get that to work either.
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
void apply_f(vector<double>& vec, double (*f)(double)) {
transform(vec.begin(), vec.end(), vec.begin(), f);
}
int main() {
vector<double> x {1, 2, 3};
auto f = [](double x){ return x + 5; };
apply_f(x, f);
cout << x[0] << endl;
cout << x[1] << endl;
cout << x[2] << endl;
}
Simply take a parameter with a unique type:
template <class F>
void apply_f(vector<double>& vec, F f) {
transform(vec.begin(), vec.end(), vec.begin(), f);
}
Not only it will work, but you will get way better performance since the compiler knows the actual type being passed.
Unfortunately, lambdas are not just pointers to functions (because they can have state, for instance). You can change your code to use a std::function<double(double) instead of a double(*)(double), and this can capture a lambda (you may need to pass std::cref(f) instead of just f).

How do you create a vector of function pointers that can take different arguments?

I'm trying to learn how to store functions (or rather pointers to functions) in std::vector. I have this code:
#include <iostream>
#include <vector>
void x(int i)
{
std::cout << "x is " << i << std::endl;
}
void y(int i, int j)
{
std::cout << "y is " << i << " and " << "j" << std::endl;
}
int main()
{
std::vector<void(*)(int)> V;
V.push_back(x);
V[0](1);
return 0;
}
This works perfectly but the problem is that I can't push_back function y into the same vector since it takes 2 integers instead of one.
What should I do to store both functions in the same vector?
There is no good way to do what you want, but you can do it.
Write an augmented variant (std or boost or hand rolled tagged typesafe union) that supports implicit cast-from with exception if you get the type wrong (feel free to support conversion between types if desired). Call this poly_arg<Ts...>
Write a type eraser that takes an arg type as a template parameter. It then takes a function pointer at construction, and type erases calling it with a vector of just the right length of arguments. (Or a function object and an arg count range). It then has a vararg operator() that forwards its arguments into a vector of its arg type, then tries to call using the above type erasure. If the wrong number of arguments is passed, it throws an exception. Call this vararg_func<T>.
Store a vector of vararg_func<poly_arg<int, double, std::string>> (list of 3 types is just an example). This can store void(*)(int) and void(*)(int,int) and void(*)(std::string, double, int) and void(*)() etc, and you can invoke it. If you get the argument count wrong, you get an exception (from vararg func). If you get an argument type wrong, exception (from poly arg). If you pass an incompatible function pointer, compile error at push_back (which is great!)
If you only need to support int args you can skip poly_arg and store vararg_func<int> instead.
I think this is a bad plan.
You very very rarely want to treat functions with different numbers and types of arguments uniformly. The few legitimate cases are best handled with two coupled type erasing systems (like efficient massive customization point tables with non-uniform signatures) that hide the type unsafety internally.
Instead this plan matches your requirements, which forces type unsafety in its interface and pollutes your code with "dunno, maybe it will work" calls.
If you want help implementing those type erasers, realize that I both know how to write them and how they solved your problem and in my opinion they are a really bad idea. If that fails to deter you, go and learn about type erasure in C++ and value-type polymorphism and how std::function works. Try to write a toy std::function. Play with a "view-only" and "move-only" version. Try a zero-allocation with bounded function object size. That should take a few weeks or years.
Now write some more simple cases, like printing to an ostream. Get good enough at it. At which point vararg_func shoukd be challenging but doable; try it. If it fails, ask SO to help, including your attempt.
poly_arg should be easy in comparison.
What you want is neither possible nor reasonable. It's not possible because function pointers are typed, and a pointer to a void(int, int) is a different type from a pointer to a void(int). vector is a homogeneous container; all of its elements must be the same type. And the two types are unrelated; you cannot cast the pointer to one type into a pointer to another and expect calling it to work.
The best you can do is use a variant of pointers to different function types. Now, I have no idea how you would call those functions, since the different types take different parameter lists. How could you call it through a visitor functor? Do you have enough parameters to forward to the function in question? If not, then what's the point?
Unless you know a priori that index X in the list has a specific parameter list, and you have those parameters to pass to it, then there is no effective way to call it. And if you do know that, then what you probably want is a tuple or struct of function pointers, not a runtime container of them.
You could use std::variant if you have access to C++17:
#include <variant>
std::vector<std::variant<void(*)(int), void(*)(int, int)>> V;
V.push_back(x);
V.push_back(y);
But this gets messy real fast (if you want to add even more function types etc) and since there are different parameter types and amounts there's no sure way to uniformly call them from out of the vector unless you also store their type information and std::get the correct variant.
First of all, i would recomend using std::function over function pointers. They are more generic and can be filled with a function pointer, function object or lambda expression. The typical useage looks like this:
#include <iostream>
#include <functional>
struct Funktor { // This is a callable class/object
void operator()() {
std::cout << "Funktor called." << std::endl;
}
};
void function() { // Normal function
std::cout << "Function called." << std::endl;
};
int main()
{
std::function<void()> lambdaFunction = [](){ std::cout << "lambda function executed." << std::endl;}; // And a lambda expression (fancy way to write a function where you need it)
std::function<void()> functionPointer = &function;
std::function<void()> callableObject = Funktor();
//This is the way you call functions with a std::function object, just like with a normal function
lambdaFunction();
functionPointer();
callableObject();
return 0;
}
But this does not solve your problem of storing functions with different arguments in a std::vector. Since they have a differen signature you have to treat them as if they are different types. Like int and std::string.
To store elements with different types, the STL offers std::tuple. You can use this one to achieve your goal.
#include <iostream>
#include <functional>
#include <tuple>
int main()
{
// std::tuple takes multiple template arguments. Each corresponds to one element in the tuple
std::tuple<
std::function<void()>,
std::function<void(int)>
> functionTuple;
// To access a element of the tuple we call std::get<i> on the tuple
// This will return a reference to the element in the tuple and we
// can overwrite it with whatever we want
std::get<0>(functionTuple) = [](){
std::cout << "Function without arguments." << std::endl;
};
std::get<1>(functionTuple) = [](int arg){
std::cout << "Function without int as argument. Arg = " << arg << std::endl;
};
// We use std::get to get the function and the call it.
// The the trailing '()' and '(5)' are the actual function calls,
// just like in the example above
std::get<0>(functionTuple)();
std::get<1>(functionTuple)(5);
// You can also use std::get<...> with a type as argument.
// Have a look in the docs. Its a very nice feature of tuples
return 0;
}
And if you want to achieve both, different arguments and multiple functions, you can combine std::tuple and std::vector:
#include <iostream>
#include <functional>
#include <tuple>
#include <vector>
int main()
{
std::tuple<
std::vector<std::function<void()>>,
std::vector<std::function<void(int)>>
> functionTuple;
// We use push_back in this example, since we deal with vectors.
std::get<0>(functionTuple).push_back([](){
std::cout << "Function without arguments." << std::endl;
});
std::get<1>(functionTuple).push_back([](int arg){
std::cout << "Function without int as argument. Arg = " << arg << std::endl;
});
std::get<1>(functionTuple).push_back([](int arg){
std::cout << "Another function without int as argument. Arg = " << arg << std::endl;
});
std::get<0>(functionTuple).front()();
int i = 5;
// And we use foreach, to loop over all functions which take one integer as argument
for(auto& f : std::get<1>(functionTuple)) {
f(i);
i += 5;
}
return 0;
}
That all beeing said, I will add a word of caution. Function pointers/objects and lambdas are only one tool. They are very flexible and powerful and because of this can lead you into a rabbit hole of unexpected behaviour and errors. If you do not plan to write very generic algorithms and go deep into template metaprogramming, this tool is most likely not the best to do the job. Going for different solutions like the command pattern can make your life much easier.
Another possibility would be to alter the signature of 'x' to match that of 'y', by adding an additional int parameter that could be ignored by the body of x.
Easy. Place the arguments into a structure or base class.
If you use a pointer to a base class, you can expand the genericity.
An old fashioned method is to pass a void pointer and have the function cast it correctly.
In fact you cannot push different pointer to function of different signatures into a vector as long as you cannot push different objects of different types into a vector.
class A{};
class B{};
A aObj;
B bObj;
std::vector<class A> vecA;
vecA.push_back(aObj); // ok
vecA.push_back(vecB); // error
Push only objects with the same type as your vector instance require:
#include "stdafx.h"
#include <iostream>
#include <vector>
void Foo() { std::cout << "Foo()" << std::endl; }
void Foo2() { std::cout << "Foo2()" << std::endl; }
int Bar(float) { std::cout << "Bar(float)" << std::endl; return 0; }
double Baz(int, int) { std::cout << "Baz(int, int)" << std::endl; return 0; }
int main(){
std::system("color 1f");
typedef void(*pFunc1)();
typedef int(*pFunc2)(float);
typedef double(*pFunc3)(int, int);
pFunc1 pFn1 = Foo;
pFunc1 pFn2 = Foo2;
//pFunc1 pFn3 = Bar; // error here I guess you k now why
std::vector<pFunc1> pvcFunc1;
std::vector<pFunc2> pvcFunc2;
std::vector<pFunc3> pvcFunc3;
pvcFunc1.push_back(pFn1);
pvcFunc1.push_back(pFn2);
for (int i(0); i < pvcFunc1.size(); i++) {
pvcFunc1[i]();
}
std::cout << std::endl << std::endl << std::endl;
std::cin.get();
return 0;
}
I wouldn't do that.
I can't tell you whether using both functions in one vector is possible or not -- I'm pretty sure it isn't.
You should instead make a class and use a vector of objects.

How to adapt C++ lambdas to a sink interface such as back_inserter et al

I would like to know if its possible without having to define an extra class, if a lambda can be adapted to act as a sink.
For example we currently can do the following:
std::vector<int> ilst;
std::copy(ilst.begin(),ilst.end(),std::ostream_iterator<int>(std::cout,"\n"));
What if something like the following could be possible? obviously the following wont
compile atm:
std::copy(ilst.begin(),ilst.end(),
[](const int& i)
{
std::cout << i << "\n";
});
I've been able to get around this problem, by defining a function object that implements dereference and function operators and takes a lambda as a predicate.
However I was wondering if there is some kind of C++ voodoo that will allow for the above without the need for an extra intermediary class to be provided?
You cannot do this without an adapter object.
std::copy takes an output iterator which conforms to the standard library output iterator requirements. A lambda function is an object that has an operator() that takes certain arguments and returns a value. These are two different kinds of things.
If you have an interface that takes Y, but you have a X, the only way to reconcile this is to introduce a Z that converts X into Y.
And since X and Y are objects, Z must therefore be an object that provides the Y interface, but internally converts it into an X. Z is commonly called an adapter object.
There is no alternative "C++ voodoo" that's going to change this. There is no "other solution". You must use some kind of adapter. Whether it's a temporary of a class type or a function that returns an instance of a class, this can only be resolved with an adapter object.
Applied to this particular situation - X is a lambda, Y is an output iterator, and Z is a function_output_iterator:
#include <boost/function_output_iterator.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> ilst;
boost::copy(
ilst,
boost::make_function_output_iterator(
[](int i) { std::cout << i << "\n"; }));
}
Would this do what you expect?
std::for_each(ilst.begin(),ilst.end(),
[](const int& i)
{
std::cout << i << "\n";
});
I suspect that this example is a stand-in for something more complicated, where for_each is unsuitable. Is this so?

Lambda Expression vs Functor in C++

I wonder where should we use lambda expression over functor in C++. To me, these two techniques are basically the same, even functor is more elegant and cleaner than lambda. For example, if I want to reuse my predicate, I have to copy the lambda part over and over. So when does lambda really come in to place?
A lambda expression creates an nameless functor, it's syntactic sugar.
So you mainly use it if it makes your code look better. That generally would occur if either (a) you aren't going to reuse the functor, or (b) you are going to reuse it, but from code so totally unrelated to the current code that in order to share it you'd basically end up creating my_favourite_two_line_functors.h, and have disparate files depend on it.
Pretty much the same conditions under which you would type any line(s) of code, and not abstract that code block into a function.
That said, with range-for statements in C++0x, there are some places where you would have used a functor before where it might well make your code look better now to write the code as a loop body, not a functor or a lambda.
1) It's trivial and trying to share it is more work than benefit.
2) Defining a functor simply adds complexity (due to having to make a bunch of member variables and crap).
If neither of those things is true then maybe you should think about defining a functor.
Edit: it seems to be that you need an example of when it would be nice to use a lambda over a functor. Here you go:
typedef std::vector< std::pair<int,std::string> > whatsit_t;
int find_it(std::string value, whatsit_t const& stuff)
{
auto fit = std::find_if(stuff.begin(), stuff.end(), [value](whatsit_t::value_type const& vt) -> bool { return vt.second == value; });
if (fit == stuff.end()) throw std::wtf_error();
return fit->first;
}
Without lambdas you'd have to use something that similarly constructs a functor on the spot or write an externally linkable functor object for something that's annoyingly trivial.
BTW, I think maybe wtf_error is an extension.
Lambdas are basically just syntactic sugar that implement functors (NB: closures are not simple.) In C++0x, you can use the auto keyword to store lambdas locally, and std::function will enable you to store lambdas, or pass them around in a type-safe manner.
Check out the Wikipedia article on C++0x.
Small functions that are not repeated.
The main complain about functors is that they are not in the same place that they were used. So you had to find and read the functor out of context to the place it was being used in (even if it is only being used in one place).
The other problem was that functor required some wiring to get parameters into the functor object. Not complex but all basic boilerplate code. And boiler plate is susceptible to cut and paste problems.
Lambda try and fix both these. But I would use functors if the function is repeated in multiple places or is larger than (can't think up an appropriate term as it will be context sensitive) small.
lambda and functor have context. Functor is a class and therefore can be more complex then a lambda. A function has no context.
#include <iostream>
#include <list>
#include <vector>
using namespace std;
//Functions have no context, mod is always 3
bool myFunc(int n) { return n % 3 == 0; }
//Functors have context, e.g. _v
//Functors can be more complex, e.g. additional addNum(...) method
class FunctorV
{
public:
FunctorV(int num ) : _v{num} {}
void addNum(int num) { _v.push_back(num); }
bool operator() (int num)
{
for(int i : _v) {
if( num % i == 0)
return true;
}
return false;
}
private:
vector<int> _v;
};
void print(string prefix,list<int>& l)
{
cout << prefix << "l={ ";
for(int i : l)
cout << i << " ";
cout << "}" << endl;
}
int main()
{
list<int> l={1,2,3,4,5,6,7,8,9};
print("initial for each test: ",l);
cout << endl;
//function, so no context.
l.remove_if(myFunc);
print("function mod 3: ",l);
cout << endl;
//nameless lambda, context is x
l={1,2,3,4,5,6,7,8,9};
int x = 3;
l.remove_if([x](int n){ return n % x == 0; });
print("lambda mod x=3: ",l);
x = 4;
l.remove_if([x](int n){ return n % x == 0; });
print("lambda mod x=4: ",l);
cout << endl;
//functor has context and can be more complex
l={1,2,3,4,5,6,7,8,9};
FunctorV myFunctor(3);
myFunctor.addNum(4);
l.remove_if(myFunctor);
print("functor mod v={3,4}: ",l);
return 0;
}
Output:
initial for each test: l={ 1 2 3 4 5 6 7 8 9 }
function mod 3: l={ 1 2 4 5 7 8 }
lambda mod x=3: l={ 1 2 4 5 7 8 }
lambda mod x=4: l={ 1 2 5 7 }
functor mod v={3,4}: l={ 1 2 5 7 }
First, i would like to clear some clutter here.
There are two different things
Lambda function
Lambda expression/functor.
Usually, Lambda expression i.e. [] () {} -> return-type does not always synthesize to closure(i.e. kind of functor). Although this is compiler dependent. But you can force compiler by enforcing + sign before [] as +[] () {} -> return-type. This will create function pointer.
Now, coming to your question. You can use lambda repeatedly as follows:
int main()
{
auto print = [i=0] () mutable {return i++;};
cout<<print()<<endl;
cout<<print()<<endl;
cout<<print()<<endl;
// Call as many time as you want
return 0;
}
You should use Lambda wherever it strikes in your mind considering code expressiveness & easy maintainability like you can use it in custom deleters for smart pointers & with most of the STL algorithms.
If you combine Lambda with other features like constexpr, variadic template parameter pack or generic lambda. You can achieve many things.
You can find more about it here
As you pointed out, it works best when you need a one-off and the coding overhead of writing it out as a function isn't worth it.
Conceptually, the decision of which to use is driven by the same criterion as using a named variable versus a in-place expression or constant...
size_t length = strlen(x) + sizeof(y) + z++ + strlen('\0');
...
allocate(length);
std::cout << length;
...here, creating a length variable encourages the program to consider it's correctness and meaning in isolation of it's later use. The name hopefully conveys enough that it can be understood intuitively and independently of it's initial value. It then allows the value to be used several times without repeating the expression (while handling z being different). While here...
allocate(strlen(x) + sizeof(y) + z++ + strlen('\0'));
...the total code is reduced and the value is localised at the point it's needed. The only thing to "carry forwards" from a reading of this line is the side effects of allocation and increment (z), but there's no extra local variable with scope or later use to consider. The programmer has to mentally juggle less state while continuing their analysis of the code.
The same distinction applies to functions versus inline statements. For the purposes of answering your question, functors versus lambdas can be seen as just a particular case of this function versus inlining decision.
I tend to prefer Functors over Lambdas these days. Although they require more code, Functors yield cleaner algorithms. The below comparison between find_id and find_id2 showcase that result. While both yield sufficiently clean code, find_id2 is slightly easier to read as the MatchName(name) definition is extracted from (and secondary to) the primary algorithm.
I would argue, however, that the Functor code should be placed inside implementation files right above the function definition where it is used to provide direct access to the function definition. Otherwise a Lambda would be better for code-locality/organization.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
struct Person {
int id;
string name;
};
typedef vector<Person> People;
int find_id(string const& name, People const& people) {
auto MatchName = [name](Person const& p) -> bool
{
return p.name == name;
};
auto found = find_if(people.begin(), people.end(), MatchName);
if (found == people.end()) return -1;
return found->id;
}
struct MatchName {
string const& name;
MatchName(string const& name) : name(name) {}
bool operator() (Person const& person)
{
return person.name == name;
}
};
int find_id2(string const& name, People const& people) {
auto found = find_if(people.begin(), people.end(), MatchName(name));
if (found == people.end()) return -1;
return found->id;
}
int main() {
People people { {0, "Jim"}, {1, "Pam"}, {2, "Dwight"} };
cout << "Pam's ID is " << find_id("Pam", people) << endl;
cout << "Dwight's ID is " << find_id2("Dwight", people) << endl;
}
The Functor is self-documenting by default; but Lambda's need to be stored in variables (to be self-documenting) inside more-complex algorithm definitions. Hence, it is preferable to not use Lambda's inline as many people do (for code readability) in order to gain the self-documenting benefit as shown above in the MatchName Lambda.
When a Lambda is stored in a variable at the call-site (or used inline), primary algorithms are slightly more difficult to read. Since Lambdas are secondary in nature to algorithms where they are used, it is preferable to clean up the primary algorithms by using self-documenting subroutines (e.g. Functors). This might not matter as much in this example, but if one wanted to use more complex algorithms it can significantly reduce the burden interpreting code.
Functors can be as simple (as in the example above) or complex as they need to be. Sometimes complexity is desirable and cases for dynamic polymorphism (e.g. for strategy/decorator design patterns; or their template-equivalent policy types). This is a use-case Lambda's can not satisfy.
Functors require explicit declaration of capture variables without polluting primary algorithms. When more-and-more capture variables are required by Lambda's the tendency is to use a blanket-capture like [=]. But this reduces readability greatly as one must mentally jump between the Lambda definition and all surrounding local variables, possibly member variables, and more.

C++ STL - iterate through everything in a sequence

I have a sequence, e.g
std::vector< Foo > someVariable;
and I want a loop which iterates through everything in it.
I could do this:
for (int i=0;i<someVariable.size();i++) {
blah(someVariable[i].x,someVariable[i].y);
woop(someVariable[i].z);
}
or I could do this:
for (std::vector< Foo >::iterator i=someVariable.begin(); i!=someVariable.end(); i++) {
blah(i->x,i->y);
woop(i->z);
}
Both these seem to involve quite a bit of repetition / excessive typing. In an ideal language I'd like to be able to do something like this:
for (i in someVariable) {
blah(i->x,i->y);
woop(i->z);
}
It seems like iterating through everything in a sequence would be an incredibly common operation. Is there a way to do it in which the code isn't twice as long as it should have to be?
You could use for_each from the standard library. You could pass a functor or a function to it. The solution I like is BOOST_FOREACH, which is just like foreach in other languages. C+0x is gonna have one btw.
For example:
#include <iostream>
#include <vector>
#include <algorithm>
#include <boost/foreach.hpp>
#define foreach BOOST_FOREACH
void print(int v)
{
std::cout << v << std::endl;
}
int main()
{
std::vector<int> array;
for(int i = 0; i < 100; ++i)
{
array.push_back(i);
}
std::for_each(array.begin(), array.end(), print); // using STL
foreach(int v, array) // using Boost
{
std::cout << v << std::endl;
}
}
Not counting BOOST_FOREACH which AraK already suggested, you have the following two options in C++ today:
void function(Foo& arg){
blah(arg.x, arg.y);
woop(arg.z);
}
std::for_each(someVariable.begin(), someVariable.end(), function);
struct functor {
void operator()(Foo& arg){
blah(arg.x, arg.y);
woop(arg.z);
}
};
std::for_each(someVariable.begin(), someVariable.end(), functor());
Both require you to specify the "body" of the loop elsewhere, either as a function or as a functor (a class which overloads operator()). That might be a good thing (if you need to do the same thing in multiple loops, you only have to define the function once), but it can be a bit tedious too. The function version may be a bit less efficient, because the compiler is generally unable to inline the function call. (A function pointer is passed as the third argument, and the compiler has to do some more detailed analysis to determine which function it points to)
The functor version is basically zero overhead. Because an object of type functor is passed to for_each, the compiler knows exactly which function to call: functor::operator(), and so it can be trivially inlined and will be just as efficient as your original loop.
C++0x will introduce lambda expressions which make a third form possible.
std::for_each(someVariable.begin(), someVariable.end(), [](Foo& arg){
blah(arg.x, arg.y);
woop(arg.z);
});
Finally, it will also introduce a range-based for loop:
for(Foo& arg : my_someVariable)
{
blah(arg.x, arg.y);
woop(arg.z);
}
So if you've got access to a compiler which supports subsets of C++0x, you might be able to use one or both of the last forms. Otherwise, the idiomatic solution (without using Boost) is to use for_eachlike in one of the two first examples.
By the way, MSVS 2008 has a "for each" C++ keyword. Look at How to: Iterate Over STL Collection with for each.
int main() {
int retval = 0;
vector<int> col(3);
col[0] = 10;
col[1] = 20;
col[2] = 30;
for each( const int& c in col )
retval += c;
cout << "retval: " << retval << endl;
}
Prefer algorithm calls to hand-written loops
There are three reasons:
1) Efficiency: Algorithms are often more efficient than the loops programmers produce
2) Correctness: Writing loops is more subject to errors than is calling algorithms.
3) Maintainability: Algorithm calls often yield code that is clearer and more
straightforward than the corresponding explicit loops.
Prefer almost every other algorithm to for_each()
There are two reasons:
for_each is extremely general, telling you nothing about what's really being done, just that you're doing something to all the items in a sequence.
A more specialized algorithm will often be simpler and more direct
Consider, an example from an earlier reply:
void print(int v)
{
std::cout << v << std::endl;
}
// ...
std::for_each(array.begin(), array.end(), print); // using STL
Using std::copy instead, that whole thing turns into:
std::copy(array.begin(), array.end(), std::ostream_iterator(std::cout, "\n"));
"struct functor {
void operator()(Foo& arg){
blah(arg.x, arg.y);
woop(arg.z);
}
};
std::for_each(someVariable.begin(), someVariable.end(), functor());"
I think approaches like these are often needlessly baroque for a simple problem.
do i=1,N
call blah( X(i),Y(i) )
call woop( Z(i) )
end do
is perfectly clear, even if it's 40 years old (and not C++, obviously).
If the container is always a vector (STL name), I see nothing wrong with an index and nothing wrong with calling that index an integer.
In practice, often one needs to iterate over multiple containers of the same size simultaneously and peel off a datum from each, and do something with the lot of them. In that situation, especially, why not use the index?
As far as SSS's points #2 and #3 above, I'd say it could be so for complex cases, but often iterating 1...N is often as simple and clear as anything else.
If you had to explain the algorithm on the whiteboard, could you do it faster with, or without, using 'i'? I think if your meatspace explanation is clearer with the index, use it in codespace.
Save the heavy C++ firepower for the hard targets.