I have following code example. I am passing the pointer to a function. When I pass the pointer to the function it seems the function initializes the argument to some random number. But, when I pass the address of the variable to the function it gives expected result.
// find_if example
#include <iostream> // std::cout
#include <algorithm> // std::find_if
#include <vector> // std::vector
class A
{
public:
A(int i) { num = i; }
bool IsPresent (A& a) {
std::cout << "Comparing " << num << " vs " << a.num << '\n';
return (num == a.num);
};
int num;
};
int main () {
std::vector<A*> myvector;
A a1(10);
A a2(20);
A a3(30);
A a4(40);
A a(40);
const A *pa = &a;
std::cout << "pa is " << pa << '\n';
myvector.push_back(&a1);
myvector.push_back(&a2);
myvector.push_back(&a3);
myvector.push_back(&a4);
std::vector<A*>::iterator it = std::find_if (myvector.begin(), myvector.end(),
std::bind2nd(std::mem_fun(&A::IsPresent), pa));
if (it != myvector.end())
std::cout << "The first equal value is " << (*it)->num << '\n';
else
std::cout << "Cannot find a match";
return 0;
}
Why the function bool IsPresent (A& a) initializes the variable (A& a) to random value when the parameter is passed by pointer and works when I pass reference of it?
When passed as pointer the result is
pa is 0x7b10b4d52e80
Comparing 10 vs -1261097344
Comparing 20 vs -1261097344
Comparing 30 vs -1261097344
Comparing 40 vs -1261097344
Cannot find a match
When Passed as reference:
pa is 0x75002e9dbb30
Comparing 10 vs 40
Comparing 20 vs 40
Comparing 30 vs 40
Comparing 40 vs 40
The first equal value is 40
And why the code compiles in first place? The function I am calling expects a reference and I am passing a pointer. Shouldn't the compiler give a warning/error as function not found?
std::bind2nd is really poorly designed.
template< class F, class T >
std::binder2nd<F> bind2nd( const F& f, const T& x )
evaluates to:
std::binder2nd<F>(f, typename F::second_argument_type(x))
and yes, that is a C-style cast.
We end up with doing an (A&)(pa), which becomes reinterpret_cast<A&>(pa).
Which reinterprets the memory of the pointer to A as an instance of A.
Did I say that bind2nd was poorly designed? I meant it.
C++11 brings lambdas and std::bind, both of which are head and shoulders and body and feet and foundation and planet above bind2nd and bind1st.
There is a reason why std::bind2nd is deprecated and removed from the standard. This is only part of the reason (also because it relies on its function arguments telling it what the argument types are, which std::bind does not).
std::mem_fun is also deprecated and removed from the standard, but it does nothing wrong here. Still, replace it with std::mem_fn which does the same job but better as a first step.
Your code will fail to compile if you blindly replace std::mem_fun with std::mem_fn and std::bind2nd with std::bind( first_arg, std::_1, second_arg ) unless second_arg matches the right type. It will do so in a spew of template spam.
Better is:
std::vector<A*>::iterator it = std::find_if (
myvector.begin(), myvector.end(),
[pa](A* a){ a->IsPresent(*pa); }
);
which if you forget to dereference pa generates a really simple and easy to read compiler error message.
Why the function bool IsPresent (A& a) initializes the variable (A& a) to random value when the parameter is passed by pointer and works when I pass reference of it?
The "A& a" parameter is defined as a reference variable, when you pass the pointer object, it is trying to interpret the object as a reference. The correct way is pass its content.
In order to improve your solution, you can define isPresent as bool isPresent(const A& a)
And why the code compiles in first place? The function I am calling expects a reference and I am passing a pointer. Shouldn't the compiler give a warning/error as function not found?
It can be interpreted wrongly as a reference. As a result it compile correctly but the execution fails.
Related
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).
I want to use for example this array of pointers to functions, without using STL.
That array is an array of pointers that I call functions OptionA, OptionB and so on.
int(*Functions[4])();
Functions[0] = OpionA;
Functions[1] = OptionB;
Functions[2] = OptionC;
Functions[0] = Exit;
Now if I write inside the function where I have my array
Functions[0];
I want to have called function 'OptionA' where it has been defined before for example like this:
int OptionA()
{
cout << "OPTION A";
_getch();
return 0;
}
Is it possible to do this without STL?
If not, I would like to know how to do it with STL.
You can create and pass arrays of function pointers like any other types. It's easiest if you have a type alias (my example leverages using, but typedef will also work).
#include <iostream>
using Function = int (*)(int, int);
int add(int a, int b) {
return a + b;
}
int sub(int a, int b) {
return a - b;
}
void do_stuff(int a, int b, Function * fns, int cnt) {
for(auto i = 0; i < cnt; ++i) {
std::cout << "Result " << i << " = " << fns[i](a, b) << '\n';
}
}
int main() {
Function fns[2] = { add, sub };
do_stuff(10, 7, fns, 2);
return 0;
}
Output:
Result 0 = 17
Result 1 = 3
I think that what you are looking for is
How to initialize a vector of pointers
Once your vector is initialize you can send it to a function like a normal data type.
Example:
std::vector<int*> array_of_pointers{ new int(0), new int(1), new int(17) };
function(array_of_pointers);
In the declaration of the function
void function(std::vector<int*> array_of_pointers);
I hope this answer your question.
In C and C++, arrays are second-class. They cannot be passed by value by themselves, only if somehow wrapped.
As a first step, the questions you have to decide are:
Does your array have a fixed length?
And do you have to pass it by value or can you pass it by reference?
If you have to pass it by value, is that a choice you want the caller to make, or the callee to impose? In the first case, pass it by reference.
If you pass the array by reference, nothing can beat using a gsl::span, unless you pass multiple sequences all having intrinsically the same length, in which case passing pointers and a single length-argument is more efficient and maybe comfortable.
If you pass an array of variable length by value, try to use a std::vector. That's also the go-to type to pass a by-ref argument as if by-value.
Otherwise (array of fixed length, by value), nothing beats std::array.
If p is a pointer to a function, which receives no parameters, you should call it by this syntax:
p();
So, if array is an array of pointers to functions, you should call one of them using the same syntax idea:
array[0]();
Here the parentheses are important; they say "call this function, and pass no parameters to it". If you have no parentheses
array[0];
this means "select this function from the array, but do nothing with it".
It's a useless expression, like if you have an integer x, then x * 5 means "multiply x by 5 and do nothing with the result" (useless), while x *= 5 means "multiply x by 5 and replace x with the result".
I created a map of type map<T, const T&>. For current example purpose, let say T is:
class Bar {
public:
Bar(int x) {this->x = x;}
int x;
};
Next I create a map and insert Bar keyed with some integers.
Bar bs[] = {Bar(1), Bar(2), Bar(3)};
map<int, const Bar&> my_map;
for (int i = 0; i < 3; i++) {
const Bar &b = bs[i];
cout << "Setting map." << i
<< " with x = " << b.x << endl ;
my_map.insert(std::make_pair(i, b));
}
So far everything looks good, and b.x prints the values 1; 2; 3 as expected. Next we retrieve these values back.
for (int i = 0; i < 3; i++) {
auto iter = my_map.find(i);
if (iter == my_map.end()) {
cout << "Not found!" << endl;
continue;
}
cout << "map." << i << " = " << iter->second.x << endl;
}
The output prints the last value each time as shown below.
// map.0 = 3
// map.1 = 3
// map.2 = 3
And that's what is confusing to me, as I expect 1; 2; 3. If I replace value type of map with just const Bar it gives 1; 2; 3. I've been trying to make sense out of it, but so far it just looks like undefined behaviour to me. The wildest explanation I can imagine is that &b is like a box storing pointer to the object, and the box ends up being shared across loop, and make_pair uses &b as a box value than like a pointer/reference (and hence explains the last value being printed).
Edit: I understand it may not be good idea to use map like this, but I'm curious why this is happening than what should I be using instead. As in semantically, what did I miss when I wrote this and why it went through compiler, or why compiler made whatever assumption it made.
Edit: Example on repl.it running the code: https://repl.it/repls/IgnorantExhaustedBluejay
Essentially the same problem as here: How can I have a pair with reference inside vector?
Your call to std::make_pair creates a temporary std::pair object that does not have a reference as its second member. The second member of the pair is a regular value of type Bar. Meanwhile, your map stores references. The reference gets bound to the second member of the temporary created by std::make_pair. Later the temporary gets destroyed. The reference becomes dangling.
Each temporary on each iteration of the cycle is apparently created at the same location in memory. So, all these dangling references in your map refer to the same location in memory. Which just happens to hold the residual value of 3 at the time of printing. That explains the output.
A map with raw references is not a very good idea. But if you want to somehow force it to work with raw references, stop using std::make_pair. Instead, manually construct a proper std::pair, making sure to explicitly specify the proper types
my_map.insert(std::pair<const int, const Bar &b>(i, b));
Or you can keep using std::make_pair as follows
my_map.insert(std::make_pair(i, std::cref(b)));
But switching entirely to std::reference_wrapper and std::cref is a better idea.
P.S. BTW, in C++17 mode GCC refuses to compile the code with raw references. C++14 mode does compile it.
I wasn't even aware that it's possible to have a map of references
You should probably simply store the object you want directly :
map<int, Bar> my_map;
If you want the "Bar"s objects to live outside the map, you should use pointers instead of references. Just be sure you don't destruct the Bar objects without removing them from the map :
map<int, Bar*> my_map;
my_map[2] = &bs[0];
and then:
int x = my_map[2]->x;
Edit
I think the map is holding a reference to the temporary pair. You can see this in debug if you extract the creation of the pair :
auto tempPair = std::make_pair(i, b);
my_map.insert(tempPair);
Then after adding bs[0] if we run the creation of the pair, the value of my_map[0] change even before adding the second one:
This makes it work:
my_map.insert(std::make_pair(i, std::reference_wrapper<const Bar>(b)));
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.
Per my understanding, Functor should be used as this
std::greater<int> g;
std::cout << std::boolalpha << g(10, 3) << std::endl;
or as parameter of a function.
find_if(v.begin(), v.end(), std::greater<int>())
but what does this mean?
std::cout << std::greater<int>()(100, 300) << std::endl; // output: false
And when I use not_equal_to as below, it cannot pass compile:
int* pt = std::adjacent_find (numbers, numbers+5, std::not_equal_to<int>(1,1)) +1;
Why is it working?
In the 1st code, you're calling operator() on the functor, and print out the result.
std::cout << std::greater<int>()(100, 300) << std::endl; // output: false
~~~~~~~~~~~~~~~~~~~ <- create a temporary object(functor)
~~~~~~~~~~ <- call operator() on the temporary object
Why isn't it working?
In the 2nd code, you're passing the functor to an algorithm, and the functor will be called inside the algorithm, by calling operator() on it.
int* pt = std::adjacent_find (numbers, numbers+5, std::not_equal_to<int>(1,1)) +1;
~~~~~~~~~~~~~~~~~~~~~~~~~~~
You're trying creating a temporary std::not_equal_to by a ctor taking 2 parameters. std::not_equal_to doesn't have that ctor, so just change it to use the default ctor, as you did for calling std::find_if with std::greater.
int* pt = std::adjacent_find (numbers, numbers+5, std::not_equal_to<int>()) +1;
As you know, for a class X with a parameterless constructor, you can write X() as part of other expressions to create a (temporary stack-) object. Ie. following two codes are the same [if callFunc doesn't expect a changeable reference etc.]:
X x;
callFunc(x);
callFunc(X());
Now std::greater<int>()(100, 300) creates a object of std::greater<int> like above, and the executes the functor with parameters 100 and 300. It's just a combination of your first two code samples, a pair of parenthesis for object creation and one for calling it. In std::not_equal_to<int>(1,1), you're missing a pair of parenthesis.