vector<int> vwInts;
vector<int> vwIntsB;
for(int i=0; i<10; i++)
vwInts.push_back(i);
transform(vwInts.begin(), vwInts.end(), inserter(vwIntsB, vwIntsB.begin()),
bind1st(plus<int>(), 5)); // method one
transform(vwInts.begin(), vwInts.end(), inserter(vwIntsB, vwIntsB.begin()),
bind2nd(plus<int>(), 5)); // method two
I know the usage difference between bind1st and bind2nd and both method one and method two provide the expected results for me.
Is it true that there is no big difference in this case (i.e. usage of transform) so that I can use either bind1st or bind2nd?
Since, all examples I saw so far always use the method two. I would like to know whether or not bind1st and bind2nd in above case are same.
bind1st binds the first parameter of plus<int>() functor, and bind2nd binds the second parameter. In case of plus<int>, it doesn't make any difference, as 10+20 and 20+10 are same.
But if you do that with minus<int>, it would make difference, as 10-20 and 20-10 aren't same. Just try doing that.
Illustration:
int main () {
auto p1 = bind1st(plus<int>(),10);
auto p2 = bind2nd(plus<int>(),10);
cout << p1(20) << endl;
cout << p2(20) << endl;
auto m1 = bind1st(minus<int>(),10);
auto m2 = bind2nd(minus<int>(),10);
cout << m1(20) << endl;
cout << m2(20) << endl;
return 0;
}
Output:
30
30
-10
10
Demo : http://ideone.com/IfSdt
bind1st binds the first parameter of a function while bind2nd binds the second parameter. Since the two parameter types are the same in this case and operator+ is symmetrical it makes no difference.
In this case, they'd translate respectively to 5 + a and a + 5, which gets compiled to exactly the same.
For your particular case
bind1st()
and
bind2nd()
are same.
Thus is because, plus() binary function operator looks like below
plus(arg1, arg2)
So, when you use bind1st(plus<int>(), 5) the call to plus would look as under
plus(5, vwInts)
so, above will add every element of vector with a value 5
And when you use bind2nd(plus<int>(), 5) the call to plus would look as under
plus(vwInts, 5)
so, above will add every element of vector with a value 5.
Hence both are same in your case
Related
I'm using a set of objects in C++ to get log(n) times for inserting and finding.
In the code below I'm able to insert elements and make them ordered by x attribute, however, I'm not able to use lower_bound to find the lower bounds based on the same attribute. I don't know how to fix that. Any help will be appreciated.
Most of the examples on sets that I could find were not about a set of objects
struct MyObject {
float x = 0;
float y = 0;
const bool operator < ( const MyObject &r ) const{
return ( x< r.x);
}
};
set<MyObject> nset;
int main(){
MyObject n1;
n1.x=5;
n1.y=1;
MyObject n2;
n2.x=3;
n2.y=2;
nset.insert(n1);
nset.insert(n2);
// this works, the elementes are sorted according to x
for(auto elem: nset){
cout << elem.x << endl;
}
// this doesn't work
set<MyObject>::iterator it = lower_bound(nset.begin(), nset.end(), 1.2);
cout << it->x << endl;
//neither this one
// set<MyObject>::iterator it = nset.lower_bound(1.2);
// cout << it->x << endl;
cout << "hello" << endl;
return 0;
}
I want the lower bound function to point me to the lower bound "x" in the set of objects but the code fails to compile. Compiler error to the first lower bound says: Invalid operands to binary expression ('const MyObject' and 'double')
Compiler error to the second lower bound says: No matching member function for call to 'lower_bound'
EDIT: while the answer provided by user: 1201ProgramAlarm was quite helpful for me to understand and fix the error. I still think it is more convenient in my case to have a lower_bound function that accepts floats rather than objects. So I have implemented the following function to help me achieve that. Copied below just in case others were interested:
set<MyObject>::iterator mylower_bound(set<MyObject> &myset, float val){
MyObject f;
f.x = val;
set<MyObject>::iterator it = myset.lower_bound(f);
return it;
}
nset stores MyObject objects, and lower_bound needs one of the thing stored in the set. You're passing it 1.2, which is a double, but there is no way to construct a MyObject from a double. Thus the compilation failure.
You'll need to pass a MyObject to nset.lower_bound to do your search.
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 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.
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.
I'm trying to build a function that accepts an array in the following manner:
int inCommon = findCommon({54,56,2,10}, 4);
int findCommon(int nums[], int len){
for(int i=0; i<len; i++) cout<<nums[i]<<endl;
return 1;
}
Note, that's not actually what my function does, but I do loop through the array. I'm just trying to determine if it's possible to pass an array like {54,56,2,10} instead of having to create an array and pass it? (like this:
int theArray[]= {54,56,2,10};
int inCommon = findCommon(theArray,4);
This is not possible at the time. However, in the next C++ standard C++0x, this will be done using initalizer lists:
int findCommon(std::initializer_list<int> nums)
{
std::initializer_list<int>::iterator it;
for (it = nums.begin() ; it != nums.end() ; ++it)
{
std::cout << *it << std::endl;
}
return 1;
}
See this presentation from Bjarne Stroustrup, and this article from Wikipedia
If you want to try C++0x features, you can check the last versions of gcc, that supports some of them.
You need C++0x!
http://en.wikipedia.org/wiki/C%2B%2B0x#Initializer_lists
No, I believe {} may only be used to initialize an array.
You can do what you want to do using variable argument lists.
no. It is impossible.
But you can create something like template T* arrayCreator(...) function which will create your array,
Or array wrapper with constructor with unspecified arguments count.
Or create object which will have overloaded operator coma or << and will create your array, findCommon( arrCreator() << 1 << 2 << 3 << 5, other parammeters ) - this method more type safe
Or waiting C++0x implementation.