I'm trying to extend an example I found in Koenig and Moo's "Accelerated C++." I've got the following code which attempts to split a vector into two partitions.
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
struct MyClass {
int* MyInt;
MyClass() : MyInt(NULL) {}
};
struct AnalyzeMemOps {
vector<MyClass> AllMyClassRecords; // Where I keep the MyClass instances
bool sameBaseReg(MyClass m);
vector<MyClass> splitBySameBase(vector<MyClass>& main);
AnalyzeMemOps() {}
};
// Predicate function for stable_partition
bool AnalyzeMemOps::sameBaseReg(MyClass m) {
return true;
}
vector<MyClass> AnalyzeMemOps::splitBySameBase(vector<MyClass>& main) {
vector<MyClass>::iterator it =
stable_partition(main.begin(), main.end(), sameBaseReg); // Error is here
vector<MyClass> sameBases(it, main.end());
main.erase(it, main.end());
// Print results
cout << "Split By Same Base: Returning SameBase Instrs\n";
for (vector<MyClass>::iterator i = sameBases.begin(); i != sameBases.end(); ++i) {
cout << " " << i->MyInt << "\n";
}
return sameBases;
}
int main() {
AnalyzeMemOps AMCR;
MyClass m;
AMCR.AllMyClassRecords.push_back(m);
AMCR.AllMyClassRecords.push_back(m);
AMCR.AllMyClassRecords.push_back(m);
vector<MyClass> t = AMCR.splitBySameBase(AMCR.AllMyClassRecords);
}
I get an error when I attempt to compile this file with g++:
Tile.cpp: In member function \u2018std::vector<MyClass, std::allocator<MyClass> > AnalyzeMemOps::splitBySameBase(std::vector<MyClass, std::allocator<MyClass> >&)\u2019:
Tile.cpp:26: error: no matching function for call to \u2018stable_partition(__gnu_cxx::__normal_iterator<MyClass*, std::vector<MyClass, std::allocator<MyClass> > >, __gnu_cxx::__normal_iterator<MyClass*, std::vector<MyClass, std::allocator<MyClass> > >, <unresolved overloaded function type>)\u2019
/usr/include/c++/4.4/bits/stl_algo.h:1864: note: candidates are: _BIter std::stable_partition(_BIter, _BIter, _Predicate) [with _BIter = __gnu_cxx::__normal_iterator<MyClass*, std::vector<MyClass, std::allocator<MyClass> > >, _Predicate = bool (AnalyzeMemOps::*)(MyClass)]
make: *** [a.out] Error 1
Obviously this is a toy example, but I've checked the function prototypes and I'm not sure where I'm going wrong here. Any suggestions?
The problem is that sameBaseReg is a member function of AnalyzeMemOps. You can't use it like an ordinary non-member function because it can only be called on an object.
If you have a modern compiler that supports C++0x, C++ TR1, or if you have Boost handy, you can use bind to bind the pointer to member function to the this object:
std::bind(&AnalyzeMemOps::sameBaseReg, this, std::placeholders::_1)
In the current C++ standard library, the <functional> library has std::mem_fun, std::bind1st, and other functions that can help with this, but they are an absolute beating to use effectively.
You'll need to use mem_fun to turn the member function into an function object, then use bind1st to supply the this pointer.
I was never particularly successful getting this stuff to work on a regular basis (the standard library algorithms seem to be mainly designed for use with freestanding functions or hand-written predicate classes), but something like this should do the trick:
vector<MyClass>::iterator it =
stable_partition(main.begin(),
main.end(),
bind1st(mem_fun(&AnalyzeMemOps::sameBaseReg),
this));
mem_fun gives you back a function object that takes two arguments, the first being the object to invoke mem_fun's member function on, and the second being the single argument to the member function.
bind1st takes a function object that takes two arguments, and returns you a new one that takes one argument, which when invoked via operator() will call the original function object with the bind1st's argument as its first argument and the supplied argument as the second.
The end result is that a new function object is created, that takes one argument, and that will call this->sameBaseReg, passing in the supplied argument.
Related
I'm still new to C++ and have come across a problem where I can't seem to insert a new derived class to a map.
My code is simplified as follows:
std::map<int, std::unique_ptr<Base_Class> > m;
void func(){
for(int num = 0; num < 100; n++){
m.emplace(num, new Derived_Class() );
}
}
Which gives me this:
error: no matching function for call to 'std::pair <const int, std::unique_ptr<Base_Class> >::pair(int&, Derived_Class*)
I've tried unsuccessfully using:
m.emplace(std::pair(num, new Derived_Class()) );
And which gives me this:
error: no matching function for call to 'std::pair<const int, std::unique_ptr<Base_Class> >::pair(std::pair<int, Derived_Class*>)
I can't seem to figure this one out and would appreciate any help.
m.emplace(num, std::unique_ptr<Derived_Class>(new Derived_Class()));
Would be the way to go. Since the unique_ptr constructor taking a raw pointer is explicit, it cannot be implicitly initialized from a Derived_Class*. You need to explicitly create a unique_ptr object to emplace.
I posed this solution because you mentioned c++11, but the truly favorable way would be to use std::make_unique<Derived_Class>() (c++14 and onward), both to avoid repeating yourself, and to make the creation of the unique_ptr "atomic".
I'm having a small problem which I can't wrap my head around.
I have a function that looks like this:
template <typename T>
std::unique_ptr<Environment>& CreateEnvironment(sf::Vector2f& _position, bool _addToStatic = false);
This is my function pointer typedef
typedef std::unique_ptr<Environment>& (WorldEditor::*CreateEnvironmentPtr)(sf::Vector2f&, bool);
std::map<std::string,CreateEnvironmentPtr> listEnv;
And I'm trying to simply do this:
listEnv["test"] = &CreateEnvironment<Coin>(sf::Vector2f(200,200), false);
And i get the following error:
error C2440: '=' : cannot convert from 'std::unique_ptr<_Ty> *' to
'std::unique_ptr<_Ty> &(__thiscall WorldEditor::* )(sf::Vector2f
&,bool)'
I understand what the error is saying, but I don't know how to solve it. Also why does it even care about the return type when I'm pointing to the address of the function?
Best regards
nilo
problems such as these are often much better solved with std::function
std::map<std::string, std::function<void()> listEnv;
listEnv.emplace("test", [] {
CreateEnvironment<Coin>(sf::Vector2f(200,200), false);
});
to call:
listEnv.at("test")->second();
Based on your post I am not sure if you are attempting to create the member function pointer and map inside the CreateEnvironment class or outside of it, so I'll solve what I think is the more difficult problem of pointer to a separate object's member function.
I simplified your classes like so:
Environment
struct Environment
{
int i = 1;
};
Coin
struct Coin
{
int k = 0;
};
WorldEditor
struct WorldEditor
{
template <typename T>
std::unique_ptr<Environment> CreateEnvironment(int& _j, bool _addToStatic = false)
{
return std::make_unique<Environment>();
}
};
Solution: Map an object's member fn pointer, and then call it later
(I will be using C++11/14 syntax in my answer)
//declare a pointer to member function in WorldEditor
using CreateEnvironmentPtr = std::unique_ptr<Environment> (WorldEditor::*)(int&, bool);
//declare an object of type WorldEditor, because member function pointers need a "this" pointer
WorldEditor myWorldEditor;
int myInt = 42;
//map a string to the CreateEnvironment<Coin> function
std::map<std::string, CreateEnvironmentPtr> listEnv;
listEnv["test"] = &WorldEditor::CreateEnvironment<Coin>;
// call the member function pointer using the instance I created, as well as
// the mapped function
(myWorldEditor.*listEnv["test"])(myInt, false);
// (printing member value to cout to show it worked)
std::cout << (myWorldEditor.*listEnv["test"])(myInt, false)->i << std::endl; // prints 1
Live Demo
Solution 2: use std::bind and std::function
Perhaps we already know the parameters to the member function call at the time we create the entry for map. Using std::bind with a std::function will help us achieve that (Similar to Richard Hodges' solution):
// now our "function pointer" is really just a std::function that takes no arguments
using CreateEnvironmentPtr = std::function<std::unique_ptr<Environment>(void)>;
//declare an object of type WorldEditor, because member function pointers need a "this" pointer
WorldEditor myWorldEditor;
int myInt = 42;
//map a string to that function pointer
//ensure it gets called with the right args
// by using std::bind (which will also make the arg list appear the be void at call time)
// note that std::bind needs an instance of the class immediately after
// listing the function it should be binding
// only afterwards will we then pass the int& and bool
std::map<std::string, CreateEnvironmentPtr> listEnv;
listEnv["test"] = std::bind(&WorldEditor::CreateEnvironment<Coin>, &myWorldEditor, myInt, false);
// the mapped function
listEnv["test"]()->i;
// (printing resulting unique_ptr<Environment>'s member to cout to show it worked)
std::cout << listEnv["test"]()->i << std::endl; // prints 1
Live Demo 2
I'm coding in C++. I have a project with so many files. I have a vector of pairs named list as follows:
std::vector< std::pair< structure1, double> > list;
and I want to check if for a specific double value z , there exists an element: el in the list such that: el.second == z
I want to use find_if
To do so , I've implemented a method : Scheduled that takes two arguments: the first one is an element like those stored in the list , the second one is the specific value to look for.
I tried several ways but I end up getting an error always
1st way:
bool classA::Scheduled(std::pair< structure1,double > const el, double const t )
{
return el.second==t;
}
inside another method but still in the same class: classA
auto Scheduled1 = std::bind(&classA::Scheduled,this,_1,z);
bool call=std::find_if(list.begin(),list.end(),Scheduled1)=!list.end();
This solution gives the following error:
error: ‘Scheduled1’ does not name a type
2nd way:
directly using lambda
bool call = std::find_if(list.begin(),list.end(),[this](std::pair<struct1,double> const& el){return el.second==z;})!=list.end();
z is a member variable of classA
This second way of coding gives rise to this error:
error: no matching function for call to
‘find_if(std::vector >::iterator, std::vector >::iterator, classA::method1(int)::__lambda0)’
There's no need to mix bind, bind1st and mem_fun to do this (the latter two are deprecated in C++11); just use a lambda
bool call = std::find_if(list.begin(), list.end(),
[this](std::pair< strucure1,double > const& el) {
return el.second == z;
}) != list.end();
Or if you want to call Scheduled
bool call = std::find_if(list.begin(), list.end(),
[this](std::pair< strucure1,double > const& el) {
return Scheduled(el, z);
}) != list.end();
If you must use bind
bool call = std::find_if(list.begin(), list.end(),
std::bind(&classA::Scheduled, this, _1, z)) != list.end();
In either case, you might want to change Scheduled to be a static member function since it doesn't need access to any non-static members, in which case the bind option becomes
bool call = std::find_if(list.begin(), list.end(),
std::bind(&classA::Scheduled, _1, z)) != list.end();
Also, Scheduled should probably take the std::pair argument by const& to avoid unnecessary copies.
Another option is to use any_of instead of find_if, which avoids having to compare the result with the end interator
bool call = std::any_of(list.begin(), list.end(),
<insert lambda or bind expression>);
Here's an explanation of what's wrong with your attempt.
auto Scheduled1=std::bind(Scheduled, _1, z);
Scheduled is a non-static member function, which means it takes an implicit first argument, a pointer to the instance it must be invoked on, i.e. the this pointer. Moreover, the syntax for creating a pointer to member function is &ClassName::MemberFunctionName. So the above line should be
auto Scheduled1=std::bind(&classA::Scheduled, this, _1, z);
bind returns a function object of unspecified type, but you use that object as if it were a member function (mem_fun(&classA::Scheduled1)) which is clearly incorrect. Simply passing the above Scheduled1 object as the 3rd argument to find_if in your example should work.
As mentioned by #Praetorian, you could've used lambdas. However, binders allow one to use existing predicate functions out of the box, though, and is sometimes more readable (The fact that the new std::bind automatically binds a member function to instance, allows one to use the public interface of a type out of the box). I've added an example similar to yours (that compiles) in which I'll explain some things (see code comments):
#include <iostream>
#include <vector>
#include <utility>
#include <functional>
#include <algorithm>
// Replaces your structure...
struct Xs{};
// typedef so that we can alias the ugly thing...
typedef std::vector<std::pair<Xs, double>> XDoubleVector;
// --- From your code, I've just named it A for brevity....
struct A
{
bool Scheduled(std::pair<Xs,double> const el, double const t )
{
return el.second==t;
}
};
int main() {
using namespace std::placeholders;
//Instantiate it.... replaced your list.
XDoubleVector doubleVect;
//--- and add some elements....
//We need to instantiate A, in order to invoke
// a member function...
A a;
// Returns true if found...
return std::find_if(
doubleVect.begin(),
doubleVect.end(),
//Notes:
//- Scheduled is a member function of A
//- For that reason, we need to pass an instance of
// A to binder (almost seen as first bound).
//- _1 indicates that the first parameter to Scheduled will be
// passed in by algorithm
//- We've hardcoded the second parameter (it is therefore
// bound early).
std::bind(&A::Scheduled, a, _1, 20.9)) != doubleVect.end();
}
Regards, Werner
I am new to Boost.Threads and am trying to understand how to pass function arguments to the boost::thread_groups::create_thread() function. After reading some tutorials and the boost documentations, I understand that it is possible to simply pass the arguments to this function but I can't get this method to work.
The other method I read about is to use functors to bind the parameters to my function but that would create copies of the arguments and I strictly require that const references be passed since the arguments will be big matrices(this I plan to do by using boost::cref(Matrix) once I get this simple example to work).
Now, let's get down to the code:
void printPower(float b, float e)
{
cout<<b<<"\t"<<e<<"\t"<<pow(b,e)<<endl;
boost::this_thread::yield();
return;
}
void thr_main()
{
boost::progress_timer timer;
boost::thread_group threads;
for (float e=0.; e<20.; e++)
{
float b=2.;
threads.create_thread(&printPower,b,e);
}
threads.join_all();
cout << "Threads Done" << endl;
}
This doesn't compile with the following error:
mt.cc: In function âvoid thr_main()â:
mt.cc:46: error: no matching function for call to âboost::thread_group::create_thread(void (*)(float, float), float&, float&)â
/usr/local/boost_1_44_0/include/boost/thread/detail/thread.hpp: In member function âvoid boost::detail::thread_data<F>::run() [with F = void (*)(float, float)]â:
mt.cc:55: instantiated from here
/usr/local/boost_1_44_0/include/boost/thread/detail/thread.hpp:61: error: too few arguments to function
What am I doing wrong?
You can't pass arguments to boost::thread_group::create_thread() function, since it gets only one argument. You could use boost::bind:
threads.create_thread(boost::bind(printPower, boost::cref(b), boost::cref(e)));
# ^ to avoid copying, as you wanted
Or, if you don't want to use boost::bind, you could use boost::thread_group::add_thread() like this:
threads.add_thread(new boost::thread(printPower, b, e));
For more flexibility you can use:
-Lambda functions (C++11): What is a lambda expression in C++11?
threads.create_thread([&b,&e]{printPower(b,e);});
-Functors that store the arguments as const references.
struct PPFunc {
PPFunc(const float& b, const float& e) : mB(b), mE(e) {}
void operator()() { printPower(mB,mE); }
const float& mB;
const float& mE;
};
-std::bind (C++11) or boost::bind
I try to pass std::log as a functional argument, but it seems that there are overloaded implementations of std::log and the compiler failed to resolve it. Codes:
#include <cmath>
#include <iostream>
#include <vector>
#include <string>
#include <functional>
template <typename FOper>
double Eval(FOper fOper, double X)
{
return fOper(X);
}
int main(int argc, char* argv[])
{
std::function<double(double)> fPlus1 = std::bind(std::plus<double>(), 1.0, std::placeholders::_1);
std::cout<<Eval(fPlus1, 10.0)<<std::endl;
// how to write this fLog ?
//std::function<double(double)> fLog = std::log;
//std::function<double(double)> fLog = std::log<double>;
std::cout<<Eval(fLog, 10.0)<<std::endl;
return 0;
}
The complier prompts an error message if I uncomment either line of the definition of fLog:
error: conversion from '<unresolved overloaded function type>' to non-scalar type 'std::function<double(doubl
e)>' requested
The easiest way would be to simply cast it:
typedef double (*log_d)(double);
std::function<double(double)> fLog = static_cast<log_d>(std::log);
With the cast, you hand the compiler a context in which the overloaded function is used, and as such will get the correct function pointer out of it.
Like Xeo explained, it is possible to get it to work even when the function is overloaded using an explicit cast. However, since you're using std::function already (which is a C++11 feature), you might as well just use a lambda expression as initializer:
function<double(double)> fLog = [](double x){return std::log(x);};
This is preferable in C++11 because it avoids overloading issues. Also, it is more efficient than wrapping a function pointer because it saves one level of indirection and therefore allows the lambda's body to be inlined into the internal wrapper object's function call operator.
It should probably be stressed that the use of std::function in your example is unnecessary since Eval is already a function template and the type parameter FOper can exactly match the type of the function object without the need to wrap it inside std::function. So, if you don't need the type erasure you get by using std::function, you could just as well write
template <typename FOper>
double Eval(FOper fOper, double X)
{
return fOper(X);
}
int main()
{
auto flog = [](double x){return std::log(x);};
std::cout << Eval(flog, 10.0) << std::endl;
}
You do this:
typedef double (*logtype)(double);
std::function<double(double)> fLog = (logtype) std::log;
The cast will help compiler to select the correct overload.
You can also write this:
double (*fLog )(double) = std::log; //i.e don't use std::function
std::cout<<Eval(fLog, 10.0)<<std::endl;
The issue is that something like this on its own has no meaning:
std::bind( std::log, _1 ); // cannot resolve. bind what function? What will _1 be passed as?
log is not a template so you can't call std::log<double> in there.
You can make your own template though, that will resort to log:
template< typename T >
T logT( T t )
{
return std::log( t );
}
and now you can use logT in your code.
std::bind( logT<double>, _ 1 ) // should work.
You could of course make fLog a function pointer to logT if you want. With C++11 you can use auto etc. to not have to type out its type by hand.