Passing a pointer for a dynamic runtime function - c++

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).

Related

Making a list of generators (vector of lambdas) leads to very strange behavior with capture-by-reference

The following code is fairly similar to my actual application. Basically, I am trying to create a vector of functions so that I can generate a very large output in segments. I don't fully understand how the capture by reference [&] is working / should be working, and it's leading to some weird behavior.
#include <iostream>
#include <functional>
#include <vector>
using namespace std;
template <typename T>
T add(const T& a, const T& b) {
return a + b;
}
template <typename T>
T add(const T& a, const T& b, T x) {
return (add<T>(a,b)*x);
}
int main() {
std::cout << "Hello World!\n";
vector<function<long ()>> funks;
for (long i = 1; i < 12; ++i) {
//auto funky = std::bind(add<int>, i, i*i);
std::cout << "PROOF: " << add(i, i*i, 2L) << std::endl;
function<long ()> funky = [&]() -> long {
long V = i;
return add(V, V*V, 2L);
};
funks.push_back(funky);
}
for (auto&& x : funks) {
std::cout << x() << " ";
}
}
The output of running each x in funks is: [312, 312, 312 ... 312] corresponding to i = 13
However, I don't understand why this is the case, as I reinitialize V for each lambda, and the output should be [4, 12, 24, 40, ... 264]
It works when I change the capture clause to [=], but in my actual application the inputs will be quite large so I'd prefer to copy as few times as possible.
EDIT: I should clarify exactly what I'm looking for. I'd like to make a vector of N functions, [f_0, f_1, ... f_N], such that when calling f_i(), it calls F(V_i) for some large (known) function F and large V_i.
The reason I want to capture by reference is that I don't want to copy the V_i even once, but the result of my implementation is that every f_i() ends up calling F(V_N)
You are auto-capturing i by reference in your loop, but it's only a binding. The value is not actually used until after the loop, when calling the lambda. At that point, each call takes the captured "reference to i" (which is actually undefined behavior, given that i is no longer in scope), dereferences it and stores the value in V. You know the rest.
What is strange is that you are insisting on using references to integer values. It's likely the compiler is doing its best to inline these and just use plain copies, but you should consider that when you have a reference, you can often expect additional instructions to be generated to dereference that to a value. For primitive types, just copy.
Oh, and definitely capture i by value!!! As a matter of style, I prefer to be explicit about my captures:
function<long ()> funky = [i]() -> long {
long V = i;
return add(V, V*V, 2L);
};

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.

Using a pair as a parameter from another function

I asked this question before but the suggestions don't work so I have tried to make my question more clear.
I have a function that returns a std::pair<int, double> but the parameters for the function as follow function(int g, double a);. This function then using make_pair to make a pair with the first being the int and the second being the double. It returns the pair.
I want to create another function to use the pair from the previous function and view the data in the pair, i.e. both first and second. Is it possible to pass the return of the previous function as a parameter for my new function so the second function can view the data? I am unsure about the syntax in C++.
It wouldn't be so hard if you rather not talked about the code but started trying to write it:
#include <iostream>
#include <utility>
std::pair<int, double> function(int g, double a)
{
return std::make_pair(g, a); // or return {g, a};
}
void print(std::pair<int, double> pair) // or take by reference-to-const
{
std::cout << pair.first << " " << pair.second << std::endl;
}
int main()
{
print(function(4, 5.5));
return 0;
}
Something's not in order if you're dealing with class templates, but don't know how to write functions.

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?

Better design for using function pointers with varying arguments

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