I try to get this code running. I am almost there but I got stuck with the line:
_f = std::bind1st(
std::mem_fun(f, x);
First of all please understand that I don't want to change any code, but the constructor. Why? Because I want to learn. Eventually I want to write a wrapper class Func, that can handle free functions and member function at the same time, in this very manner.
So what wuld I have to put as the first argument inside the std::mem_func()-call???
I tried numerous things.
Probably this is a duplicate, but I don't know how to search for this problem. I lack the vocabulary. If someone can point to a tutorial or something, that would help me to express this problem, I would also appreciate it.
Here is the full sample code:
#include <boost/function.hpp>
#include <iostream>
struct X
{
int foo(int i)
{
return i;
};
};
class Func
{
public:
Func(X *x, int (X::* f) (int))
{
_f = std::bind1st(
std::mem_fun(f, x);
std::cout << _f(5); // Call x.foo(5)
};
private:
boost::function<int (int)> _f;
};
int main()
{
X x;
Func func(&x, &X::foo);
return 0;
}
Thanks in advance.
It seems you just forgot a paren:
_f = std::bind1st(std::mem_fun(f), x);
Although I would initialize with
Func(X *x, int (X::* f) (int))
: _f(std::bind1st(std::mem_fun(f), x))
{
std::cout << _f(5); // Call x.foo(5)
};
(It doesn't matter in this case, but this style is safer in the long run.)
I would refactor the class slightly to use boost::function in the interface, and then the user can decide how to bind in the most generic way:
struct X {
int foo(int i) { return i; };
};
class Func {
boost::function<int (int)> _f;
public:
Func( boost::function<int (int)> f ){
_f = f;
std::cout << _f(5);
};
};
int foo( int x ) { return 2*x; }
int bar( int x, int multiplier ) { return x*multiplier; }
int main() {
X x;
Func func1( boost::bind( &X::foo, &x, _1 ) ); // this does the magic
Func func2( boost::bind( &foo, _1 ) ); // you can also bind free functions...
Func func3( boost::bind( &bar, _1, 5 ) ); // or with different arguments
}
Related
Note a question with nearly the exact same title already exists, but is asking a very different question.
Say I want a method that takes a bitfield reference or pointer as an argument. This isn't legal, but perhaps an example would clarify:
class Foo {
unsigned a:2, b:2, c:2;
bool Bar( unsigned* px:2 ) { *px = a; return true; };
}
Foo foo;
if ( foo.Bar( &foo.b ) )
exit( EXIT_SUCCESS );
I could write Bar as a macro:
#define BAR( pfoo, field ) ( ( (pfoo)->field = (pfoo)->a ), true )
Foo foo;
if ( BAR( &foo, b ) )
exit( EXIT_SUCCESS );
Many place where you'd write some such macro in C you can now handle with function templates. Is there a template solution to writing the above Bar() method legally in C++11 or later?
It is possible to cobble up something that acts as a bitfield reference in a rather inefficient and roundabout way.
template<typename underlying>
struct bitfield_ref
{
virtual underlying get() { return getter(); }
virtual void set(underlying val) { setter(val); }
bitfield_ref(std::function<underlying()> getter, std::function<void(underlying)> setter) :
getter(getter), setter(setter) {}
std::function<underlying()> getter;
std::function<void(underlying)> setter;
};
#define BITFIELD_REF(s,m) bitfield_ref<decltype(s.m)>( \
[&s]() { return s.m; }, \
[&s](decltype(s.m) v) { s.m = v; })
It can be used this way
struct moo
{
unsigned int a : 2;
unsigned int b : 3;
};
unsigned int test(bitfield_ref<unsigned int> x)
{
x.set(3);
return x.get() + 1;
}
int main()
{
moo m;
std::cout << test(BITFIELD_REF(m, a)) << "\n";
}
It is further possible to get rid of get and set by defining a conversion operator and an assignment operator (and all of the compound assignments to go with it), this is omitted for brevity.
In my project i have functions with different number of input parameters with different types. Since these functions are parts of libraries, I cannot change their definitions or bodies.
void methodA(boolean p1, int p2, long p3){
... some unrelevant code here ...
}
void methodB(int p1, int p2, int p3, long p4){
... some unrelevant code here too ...
}
int methodC(long p4){
...
}
In my project i need to have a method, which would receive the address of one of these functions. Additionally it receives well-formed list of parameters (which fits the function in the first parameter). Then this method has to call the passed function with the passed parameters.
Here is what I have now: (i have simplified the code a bit to make my idea clear)
void intercaller(void* some_func_address, ...){
// VARARGS parameters extractor
va_list listPointer;
va_start( listPointer, some_func_address );
int p1 = va_arg( listPointer, int );
int p2 = va_arg( listPointer, int );
int p3 = va_arg( listPointer, int );
long p4 = va_arg( listPointer, long );
// TODO: THIS IS NOT GENERIC CALL , CANN ONLY CALL METHOD B
((void (*)( int , int , int , long )) some_func_address)( p1 , p2 , p3 , p4 );
va_end( listPointer );
}
My problem is the actual function call. The parameter list in the function call should be generic and should be able to include different number of parameters, sadly i dont know how to do that... I have tried passing varargs list like here:
((void (*)( va_list )) some_func_address)( listPointer);
but this messes up the parameters in the called function...
So my question is: is there a way to call a given function with given parameters in a generic manner? Maybe I need some sort of a typedeff or a wrapper function?
If you don't have std::invoke yet, use variadic templates. To treat void functions nicely, use SFINAE.
template<typename R, typename... Args>
auto call(R(*function)(Args...), Args... args) -> typename std::enable_if<!std::is_same<R, void>::value, R>::type {
return function(args...);
}
template<typename... Args>
void call(void (*function)(Args...), Args... args) {
function(args...);
}
Example:
void a() {
std::cout << 'a';
}
void b(int a) {
std::cout << "b:" << a;
}
int c(int a) {
return a;
}
int main() {
call(a);
call(b, 1);
std::cout << "c:" << call(c, 2);
}
Don't forget to #include <type_traits> for std::enable_if and std::is_same.
Try it online!
va_args are still somewhat black magic to me, but I believe the second arg to va_start should be the first arg to the called function. I don't understand what your "clazz" is. I believe you you should call va_start as:
va_start( listpointer, some_func_address );
instead of:
va_start( listPointer, clazz );
Would this help you out?
#include <stdarg.h>
template <typename T>
T extract(va_list& list)
{
return va_arg(list, T);
}
template<typename Result, typename ... Parameters>
Result call(Result(*function)(Parameters...), va_list& list)
{
return function(extract<Parameters>(list)...);
}
void f1(int x, int y)
{
std::cout << x << ' ' << y << std::endl;
}
void f2(double x, double y)
{
std::cout << x << ' ' << y << std::endl;
}
void interceptor(void* f, ...)
{
va_list list;
va_start(list, f);
if(f == &f1)
{
call(f1, list);
}
else if(f == f2)
{
call(f2, list);
}
va_end(list);
}
int main(int argc, char* argv[])
{
interceptor((void*)&f1, 7, 7);
interceptor((void*)&f2, 10.12, 12.10);
return 0;
}
I personally would yet prefer pasing an enum representing the functions to the interceptor function instead of the void* pointer and using switch/case inside.
If you can make the interceptor a template function, it gets even much easier (drop the call template function entirely):
template<typename Result, typename ... Parameters>
void interceptor(Result(*function)(Parameters...), ...)
{
va_list list;
va_start(list, function);
function(extract<Parameters>(list)...);
va_end(list);
}
int main(int argc, char* argv[])
{
interceptor(&f1, 7, 7);
interceptor(&f2, 10.12, 12.10);
return 0;
}
Now coming from your other question, what about this:
(Side note: referenced question tells (in the comments) the void* pointers are coming from some custom map, so there shouldn't be – as far as I can see – any issue with replacing them by other appropriate pointers/classes – which I am going to do...)
#include <stdarg.h>
class FunctionWrapper
{
public:
virtual ~FunctionWrapper() { }
virtual void operator()(va_list&) = 0;
};
template<typename Result, typename ... Parameters>
class FWrapper : public FunctionWrapper
{
Result (*mFunction)(Parameters...);
template <typename T>
T extract(va_list& list)
{
return va_arg(list, T);
}
public:
FWrapper(Result (*function)(Parameters...))
: mFunction(function)
{ }
virtual void operator()(va_list& list)
{
static_cast<void>(mFunction(extract<Parameters>(list)...));
}
};
// facilitates creating the wrappers:
template<typename Result, typename ... Parameters>
FunctionWrapper* createWrapper(Result (*function)(Parameters...))
{
return new FWrapper<Result, Parameters ...>(function);
}
void f1(int x, int y)
{
std::cout << x << ' ' << y << std::endl;
}
void f2(double x, double y)
{
std::cout << x << ' ' << y << std::endl;
}
// e. g.:
FunctionWrapper* gWrappers[] = { createWrapper(&f1), createWrapper(&f2) };
// from your other question: you'd fill the wrappers into the map you mentioned there:
// map[whatever] = createWrapper(&function);
void interceptor(FunctionWrapper* wrapper, ...)
{
va_list list;
va_start(list, wrapper);
(*wrapper)(list);
va_end(list);
}
int main(int argc, char* argv[])
{
interceptor(gWrappers[0], 7, 7);
interceptor(gWrappers[1], 10.12, 12.10);
return 0;
}
This solves the issue via polymorphism: A function wrapper class template class (we need a non-template base class to be able to place all the template instances into an array or a map; this is what your original – but actually illegal – void* pointer served for), resolving the va_list into arguments and calling the original function with...
I have to solve, at least for me, a tricky problem in C++. There is a dll which i can not modify. It gets a function pointer as argument. If I pass a pointer to a global function everything works fine. Unfortunatelly there is a list of same class objects to pass to the dll. In C# I solved this by using delegates. How can this be done in C++? Using std::function does not work. With that there are coding convention errors during runtime. Further using MSVC2010 would be optimal.
I wrote a sample which describes the problem:
#include <stdio.h>
// global function which works
void __stdcall task_global(float x, float y) { printf("Called global function with: %f %f\n", x, y); }
typedef void(__stdcall *f_pointer)(float, float);
// try of using a member function
class BaseTask {
public:
virtual void __stdcall task(float x, float y) = 0;
};
class ListeningTask :public BaseTask {
public:
void __stdcall task(float x, float y) { printf("Called this member function with: %f %f\n", x, y); }
};
typedef void (BaseTask::*member_f_pointer)(float, float);
// the dll to use
class RegisterTask {
public:
// no posibility to access or modify!
void __stdcall subscribe(f_pointer fp) { fp(1.0f, 2.0f); }
// just for demonstration how to use a member function pointer
void __stdcall subscribeMemberDemo(member_f_pointer mfp) { /*how to use mfp?*/};
};
int main() {
RegisterTask register_task{};
// use global function
f_pointer pointer_to_global_task = task_global;
register_task.subscribe(pointer_to_global_task);
/*---------------------------------------------------------------*/
// use member function?
std::list<ListeningTask> listening_task_list;
for(int i = 0; i < 10; i++) {
listening_task_list.push_back(ListeningTask lt);
member_f_pointer pointer_to_member_task = &listening_task_list.back().task; //error C2276: '&': illegal operation on bound member function expression
register_task.subscribeMemberDemo(pointer_to_member_task);
// the tricky and important one to solve
// how to pass the member function to this subscribe(f_pointer)?
register_task.subscribe(pointer_to_member_task);
}
getchar();
return 0;
}
The important question is how to pass a member function pointer to the RegisterTask::subscribe(f_pointer)?
The parenthetic question is how to pass a member function to the RegisterTask::subscribeMemberDemo(member_f_pointer)?
I hope someone can help me to solve this? I am working on this since days.
Edit:
I modified the question to emphasize the problem with the list of ListenerTask. How to pass a member function pointer is now clear to me through the answers of #pokey909 and #AndyG. Both of them provide a pointer to one object or rather a list of objects. If the callback is called the one ListenerTask or all std::list<*ListenerTask> are called at once. But how to let only one ListenerTask of the list to be called. Passing more than one callback to the dll. It (RegisterTask) can do that, because the following example with global functions works.
void __stdcall task_global_1(float x, float y) { printf("Called global function 1 with: %f %f\n", x, y); }
void __stdcall task_global_2(float x, float y) { printf("Called global function 2 with: %f %f\n", x, y); }
void __stdcall task_global_3(float x, float y) { printf("Called global function 3 with: %f %f\n", x, y); }
typedef void(__stdcall *f_pointer)(float, float);
int main() {
// give the functions to the dll.
f_pointer pointer_to_global_task_1 = task_global_1;
register_task.subscribe(pointer_to_global_task_1);
f_pointer pointer_to_global_task_2 = task_global_2;
register_task.subscribe(pointer_to_global_task_2);
f_pointer pointer_to_global_task_3 = task_global_3;
register_task.subscribe(pointer_to_global_task_3);
}
There are three global function pointers. They are all given to the dll. Now, if the dll has a task for task_global_2 it notifies this only! How to achive this distinction with member function pointer?
Note:
I got the source of the dll. Hope this helps. Unfortunately modifying, building is not possible. Here is the callback definition:
type TCallback = procedure( x : single; y : single; ); stdcall;
procedure subscribe(aCallback: TCallback ); StdCall;
begin
TaskSocket.addTask( aCallback );
end;
procedure TSocket.addTask( aCallback : TCallback);
var newTask : TTask;
begin
newTask := TTask.Create(aCallback);
TaskList.addItem(newTask);
end;
You can use a freestanding function that calls a wrapper which binds your instance to it.
Here is rough example
#include <iostream>
#include <string>
#include <functional>
// global function which works
std::function<void(float, float)> memberCb;
void task_global(float x, float y) { memberCb(x, y); }
typedef void(*f_pointer)(float, float);
// try of using a member function
class BaseTask {
public:
virtual void task(float x, float y) = 0;
};
class ListeningTask :public BaseTask {
public:
void task(float x, float y) { printf("Called this member function with: %f %f\n", x, y); }
};
typedef void (BaseTask::*member_f_pointer)(float, float);
void callbackWrapper(BaseTask* t, float x, float y) { t->task(x, y); }
// the dll to use
class RegisterTask {
public:
// no posibility to access or modify!
void subscribe(f_pointer fp) {
fp(1.0f, 2.0f);
}
// just for demonstration how to use a member function pointer
void subscribeMemberDemo(member_f_pointer mfp) { /*???*/ };
};
int main() {
RegisterTask register_task{};
ListeningTask listening_task{};
memberCb = std::bind(&callbackWrapper, &listening_task, std::placeholders::_1, std::placeholders::_2);
register_task.subscribe(task_global);
return 0;
}
Note
Based on the comment, I'm not sure if all of this works in MSVC2010, since I don't have this compiler version. But rudimentary C++11 support should be in there.
Edit
I'm not sure if thats what you are after, but would this solve your problem?
void callbackWrapper(const std::list<BaseTask*> &taskList, float x, float y) {
for (auto t : taskList)
t->task(x, y);
}
int main() {
RegisterTask register_task{};
std::list<BaseTask*> taskList;
for (int i = 0; i < 4; ++i)
taskList.push_back(new ListeningTask);
memberCb = std::bind(&callbackWrapper, taskList, std::placeholders::_1, std::placeholders::_2);
register_task.subscribe(task_global);
return 0;
}
Edit 2
Ok I think I got what you want. The best I can come up with without splattering your code with global functions manually is with template magic.
Note however, that it is not as flexible as you might want because you have to bind those methods at compile time.
If you need to add them at runtime, you can probably use the same trick but without templates. Simply put all the std::function objects in a vector and wrap that up in a singleton or something similar.
#include <iostream>
#include <string>
#include <functional>
#include <list>
/* Simulated DLL */
typedef void(*f_pointer)(float, float);
class RegisterTask {
public:
void subscribe(f_pointer fp) {
fp(1.0f, 2.0f);
}
};
/* Static function generator to ease the pain to define all of them manually */
template<unsigned int T>
std::function<void(float, float)> &getWrapper() {
static std::function<void(float, float)> fnc;
return fnc;
}
/* Same here */
template<unsigned int T>
void task_global(float x, float y) { getWrapper<T>()(x, y); }
class BaseTask {
public:
virtual void task(float x, float y) = 0;
};
class ListeningTask :public BaseTask {
public:
ListeningTask(int taskNum) : m_taskNum(taskNum) {}
void task(float x, float y) { printf("Called this member of task %d function with: %f %f\n", getTaskNum(), x, y); }
int getTaskNum() const { return m_taskNum; }
private:
int m_taskNum;
};
/* Context injector */
void callbackWrapper(BaseTask* t, float x, float y) {
t->task(x, y);
}
/* Convenience function to bind an instance to a task */
template<unsigned int T>
void bindTask(ListeningTask* t) {
getWrapper<T>() = std::bind(&callbackWrapper, t, std::placeholders::_1, std::placeholders::_2);
}
int main() {
RegisterTask register_task{};
auto task0 = new ListeningTask(1337);
auto task1 = new ListeningTask(1984);
auto task2 = new ListeningTask(42);
bindTask<0>(task0);
register_task.subscribe(task_global<0>);
bindTask<1>(task1);
register_task.subscribe(task_global<1>);
bindTask<2>(task2);
register_task.subscribe(task_global<2>);
return 0;
}
Run Code demo
pokey909's answer is totally great, but if you don't even have access to std::function and std::bind, we can hack our way around it.
The gist of the approach is that we are going to define a template class with an implicit conversion to the desired function type. The downside is that each new additional wrapper requires a new type declaration.
// assumes two function arguments
template<class Ret, class Mem, class Arg1, class Arg2, int>
struct MemBind
{
typedef Ret(Mem::*mem_fn_type)(Arg1, Arg2);
static void Set(mem_fn_type _fn, Mem* _instance)
{
fn = _fn;
instance = _instance;
}
static Ret DoTheThing(Arg1 first, Arg2 second)
{
return ((*instance).*fn)(first, second);
}
typedef Ret(*fn_type)(Arg1, Arg2);
operator fn_type ()
{
return DoTheThing;
}
static mem_fn_type fn;
static Mem* instance;
};
Given some struct Foo with our desired callback:
struct Foo
{
void Bar(float a, float b)
{
std::cout << "Foo::Bar(float, float) " << a << " , " << b << std::endl;
}
};
We have to define our static members:
typedef MemBind<void, Foo, float, float, 0> MemBindZero;
template<> Foo* MemBindZero::instance = nullptr;
template<> void(Foo::*MemBindZero::fn)(float, float) = nullptr;
We can have a caller that takes in a function pointer:
void Caller(void(*_fn)(float, float))
{
_fn(42.0, 1337.0);
}
The key here is that MemBind has an implicit conversion to the desired function type. The 0 in the typedef for MemBindZero allows us to re-use the same types for the other arguments, but increment the counter to 1 when used. I think you could probably replace it with a __COUNTER__ macro or something like that, but it would be nonstandard so I did it manually.
Now the next bit is to create an instance of MemBindZero, then set the static members, and finally pass our instance into Caller:
Foo f;
MemBindZero bound;
bound.Set(&Foo::Bar, &f);
Caller(bound);
Demo
In the demo I wrapped the static member initialization into a more convenient macro:
#define MEMBIND(RET, CLASS, ARG1, ARG2, COUNT, ALIAS) \
typedef MemBind<RET, CLASS, ARG1, ARG2, COUNT> ALIAS; \
template<> CLASS * ALIAS::instance = nullptr; \
template<> RET(CLASS::*ALIAS::fn)(ARG1, ARG2) = nullptr;
So that I could call it like so:
MEMBIND(void, Foo, float, float, 0, MemBindZero)
MEMBIND(void, OtherFoo, float, float, 1, MemBindOne)
I have a Dijkstra class which uses a priority_queue with a custom compare function. I named the queue DijkstraPriorityQueue with a using statement. Inside the class constructor, I initialize the queue. To do that, I give the compare function in a lambda expression.
For the first queue, PQ1, the compare function is { return distTo[u] > distTo[v]; } and this compiles fine, because the vector<float> distTo is a member of the class.
But for the second queue, PQ2, the function is { return distTo2[u] > distTo2[v]; } where vector<float> distTo2 is just a temporary variable inside the constructor, and that doesn't compile. (I think that's the reason at least)
Also, I randomly tried to change vector<float> distTo2 to static vector<float> distTo2 by intuition and it compiles, however I don't think this is what I want to be doing. I am not familiar with static variables inside functions, since that doesn't exist in Java or C#. At any case, what is a clean solution to make the code below compile and work as intended ?
Dijkstra.h
class Dijkstra
{
public:
Dijkstra();
~Dijkstra();
private:
vector<float> distTo;
};
Dijkstra.cpp
using DijkstraPriorityQueue = priority_queue<int, vector<int>, function<bool(int, int)>>;
Dijkstra::Dijkstra()
{
distTo = vector<float>(V, FLT_MAX);
// Compiles fine
DijkstraPriorityQueue PQ1 = DijkstraPriorityQueue([this](int u, int v)
{ return distTo[u] > distTo[v]; });
vector<float> distTo2 = vector<float>(V, FLT_MAX);
// Doesn't compile
DijkstraPriorityQueue PQ2 = DijkstraPriorityQueue([this](int u, int v)
{ return distTo2[u] > distTo2[v]; });
}
Edit:
The following code compiles too. Any clues why ? Can someone explain what capture is on lambda expressions ? Or how should I write my code properly in this specific case ?
DijkstraPriorityQueue PQ2 = DijkstraPriorityQueue([distTo2](int u, int v)
{ return distTo2[u] > distTo2[v]; });
There are two main aspects of your question:
What is this “capture” thing, and why the error?
How to specify a custom compare function for a priority queue?
These aspects are most cleanly discussed separately.
Unfortunately the presented (incomplete) example code is not well suited for discussing either aspect, so I just disregard it.
What is a lambda capture.
Consider the following code:
#include <stdio.h>
struct S
{
int a_;
void foo() const
{
// Compiles nicely:
[this]() -> void { printf( "%d\n", a_ ); }();
// Doesn't compile, oh why!:
int b = 666;
[this]() -> void { printf( "%d\n", b ); }();
}
};
auto main()
-> int
{ S{ 42 }.foo(); }
MinGW g++ 5.1.0 provides the following diagnostics (compilation errors):
x1.cpp: In lambda function:
x1.cpp:14:44: error: 'b' is not captured
[this]() -> void { printf( "%d\n", b ); }();
^
x1.cpp:14:14: note: the lambda has no capture-default
[this]() -> void { printf( "%d\n", b ); }();
^
x1.cpp:13:13: note: 'int b' declared here
int b = 666;
^
To understand the “not captured”, let's implement the lambdas manually, just doing a code transformation equivalent to what the compiler does with it:
void foo() const
{
// Compiles nicely:
//[this]() -> void { printf( "%d\n", a_ ); }();
class Functor_a
{
private:
S const* captured_this_;
public:
void operator()()
{ printf( "%d\n", captured_this_->a_ ); }
Functor_a( S const* this_capture )
: captured_this_( this_capture )
{}
};
Functor_a f_a{ this };
f_a();
// Doesn't compile, oh why!:
int b = 666;
// [this]() -> void { printf( "%d\n", b ); }();
class Functor_b
{
private:
S const* captured_this_;
public:
void operator()()
{ printf( "%d\n", b ); }
Functor_b( S const* this_capture )
: captured_this_( this_capture )
{}
};
Functor_b f_b{ this };
f_b();
}
};
The diagnostic is now more clear. Since Functor_b is a class, and since a class in C++ is completely free-standing entity, its code has no relation to or access to things in a particular invocation of foo(). So the compiler doesn't accept the reference to some unspecified b, but notes that if you really meant the b in the containing scope, then hey, that name b refers to a different variable in each call of foo, and isn't a valid choice:
x2.cpp: In member function 'void S::foo() const::Functor_b::operator()()':
x2.cpp:37:35: error: use of local variable with automatic storage from containing function
{ printf( "%d\n", b ); }
^
x2.cpp:28:17: note: 'int b' declared here
int b = 666;
^
One solution is to capture the value, i.e. copy it into the functor class instance, e.g. as follows:
class Functor_b
{
private:
int const captured_b_;
public:
void operator()()
{ printf( "%d\n", captured_b_ ); }
Functor_b( int const b_capture )
: captured_b_( b_capture )
{}
};
Functor_b f_b{ b }; // ← The capture.
f_b(); // ← Using the captured value.
Alternatively you could capture a pointer to the variable, capture by reference. In that the case the pointer is only valid for the lifetime of the variable. So you'd better not keep a functor instance around after that.
Expressed in lambda notation the capture of the value can look like this:
[b]() -> void { printf( "%d\n", b ); }();
Or like this, with a general capture-whatever's-needed-by-value =:
[=]() -> void { printf( "%d\n", b ); }();
Capturing by reference, i.e. a pointer, looks like this:
[&]() -> void { printf( "%d\n", b ); }();
How to specify a compare function for a std::priority_queue.
E.g. like this:
#include <iostream>
#include <string>
#include <queue>
#include <vector>
using namespace std;
struct S
{
string name;
int birth_year;
};
auto main() -> int
{
struct Age_sort
{
auto operator()( S const& a, S const& b )
-> bool
{ return (a.birth_year < b.birth_year); }
};
using Q = priority_queue< S, vector<S>, Age_sort >;
Q pq;
pq.push( S{ "beta", 1980 } );
pq.push( S{ "alfa", 1992 } );
pq.push( S{ "charlie", 1971 } );
while( not pq.empty() )
{
cout << pq.top().name << ' ' << pq.top().birth_year << endl;
pq.pop();
}
}
Lets say I have hierarchy like this (This is just a test program. Please do not point anything related to memory leaks, destructor is not virtual etc):
class I
{
public:
virtual void fun(int n, int n1) = 0;
};
class A : public I
{
public:
void fun(int n, int n1)
{
std::cout<<"A::fun():" <<n<<" and n1:" <<n1<<"\n";
}
};
class B : public I
{
public:
void fun(int n, int n1)
{
std::cout<<"B::fun():" <<n<<" and n1:" <<n1<<"\n";
}
};
int main()
{
std::vector<I*> a;
a.push_back(new A);
a.push_back(new B);
//I want to use std::for_each to call function fun with two arguments.
}
How do I call fun() method which takes two arguments using the std::for_each ? I think I have to use std::mem_fun probably with std::bind2nd but am not able to figure out how to do this. Any clue how to achieve this? I am not using boost.
You could create your own functor like this:
class Apply
{
private:
int arg1, arg2;
public:
Apply(int n, int n1)
: arg1(n), arg2(n1)
{}
void operator() (I* pI) const
{
pI->fun(arg1, arg2);
}
};
int main ()
{
// ...
std::for_each(a.begin(), a.end(), Apply(n, n1));
}
or use boost::bind like this:
std::for_each(
a.begin(),
a.end(),
boost::bind(&I::fun, _1, n, n1));
You can't do this with the std binders. You can of course write your own functor.
struct TwoArguments
{
int one;
int two;
TwoArguments( int one, int two ) : one(one),two(two){
}
void operator()( I* i ) const {
i->fun( one, two );
}
};
Another way to do this would be to use templates. (Please tell me if it's a bad practice though!)
template<int N, int N1>
void Apply(I* i)
{
i->fun(N, N1);
}
std::for_each(a.begin(), a.end(), Apply<firstParam, secondParam>);
That would be good if you don't intend to call it with a lot of different parameters since it would generate code for every combination you made.