Compile error with compare function, C++ sort - c++

I wrote myself a compare function for sort().
It worked well when I put it this way.
bool comp(string a, string b)
{
...;
}
int main()
{
sort(...,...,comp);
}
However, when I put all this inside a class, say:
class Test {
public:
bool comp(string a,string b)
{
...;
}
vector <string> CustomSort(vector <string> str) {
sort(...,...,comp);
}
};
There is a compile error "No matching function for call to 'sort ......'.
Why would this happen?

Any nonstatic member function of class X has an extra argument - a reference/pointer to (const) X which becomes this. Therefore a member function's signature isn't such that can be digested by sort. You need to use boost::bind or std::mem_fun or std::mem_fun_ref. When using C++11, you can use std::bind.
std::sort(..., ..., std::bind(&Test::comp, this, _1, _2));
Come to think of it, the best solution in this case would be to make your comp function static, because it doesn't need this at all. In this case your original code will work without change.

Related

How to specify a class's comparator in a std::multiset

I want to create a multiset of objects of my own Class with a custom comparator, and every example I have seen out there does it without classes.
The code I have so far main.cpp is like this:
multiset<MyClass> myMultiSet;
whereas in Myclass.cpp there is a comparator function:
bool MyClass::operator<(const MyClass c) const {
return (this->data->size() < c.size());
}
Multiset seems to take the less operator by default, and it actually uses the operator< function in the class, but I cannot find a way to specify it to use another operator (such as operator<=)
For example, I would like it to look like this:
multiset<MyClass, MyClass::operator<=> myMultiSet;
bool MyClass::operator<=(const MyClass c) const { // <----- Now it's using this one
return (this->data->size() <= c.size());
}
Member functions are different to functions: they take an the this pointer. As a result, you can't use pointer-to-member-functions directly (and you would need to take the address explicitly as member functions don't decay to pointer-to-member-functions, i.e., &MyClass::operator<=). Also, the parameter is type, not a value. Also, as was pointed out, operator<= doesn't implement a strict weak order, i.e., you can't use that anyway.
The easiest to use an actual operator, whether member of not, is to use the names from <functional>, e.g.
std::multiset<MyClass, std::greater<MyClass>> s;
If the member isn't a known name, I'd think using a lambda is the easiest approach but requires C++20:
std::multiset<MyClass, decltype([](MyClass const&l, MyClass const&r){ return l.member(r); })> s;
Without C++20 I think you can use std::mem_fn although that is slightly annoying as you'll need to provide the pointer to member as a constructor argument:
#include <functional>
#include <set>
struct MyClass
{
bool member(MyClass const&) const { return false; }
};
int main()
{
std::multiset<MyClass, decltype(std::mem_fn(&MyClass::member))> s(std::mem_fn(&MyClass::member));
}

Function pointer with specific argument list

Fairly simple question:
I have a class that uses a (variable) heuristic function to perform a certain algorithm. This heuristic function should ideally be fed to the class constructor as some sort of pointer and implement the following declaration:
int heuristic_Function(GridLocation a, GridLocation b);
What is the best way to accomplish this? Ideally I would like to avoid additional classes and keep the code fairly self-contained (and yes, I am aware of things like delegates and the strategy pattern).
(This has probably been asked hundreds of times already but in different terms)
Well, as you said, you could store a function pointer:
struct Algo
{
using HeurFn = int(GridLocation, GridLocation);
Algo(HeurFn * heuristic) : heuristic_(heuristic) {}
void Run()
{
// use "heuristic_(a, b)"
}
HeurFn * heuristic_;
};
Then instantiate it:
extern int my_fn(GridLocation, GridLocation);
Algo algo(my_fn);
algo.Run();
An alternative would be to pass the function directly to Run, in which case you could make Run a template and perhaps allow for inlining of the actual heuristic code, but you explicitly asked for the heuristic to be configured via the constructor.
Instead of old C function pointer, I would recommend std::function.
So you could write it like this
#include <functional>
struct algorithm{
algorithm (std::function<int(GridLocation, GridLocation)> heuristic_function) :
heuristic(heuristic_function) {}
int do_something (GridLocation a, GridLocation b){
return heuristic(a,b);
}
private:
std::function<int(GridLocation, GridLocation)> heuristic;
}
Advantages are the better readable syntax, and that the caller can use std::bind expressions.
Or you could just take the heuristic as a template, but then you would to either make your algorithm to just a function or write the type to every new instance. See https://stackoverflow.com/a/2156899/3537677
Things get really simple if only the method that does the computations needs the function, and you can forgo storing the function in the class itself. You can then parametrize the method on the type of the passed function, and you get full flexibility:
struct Calculate {
template <typename F> int run(F && f) {
return f(1, 2);
}
};
int f1(int, int) { return 0; }
struct F2 {
int operator()(int, int) { return 0; }
};
int main() {
Calculate calc;
// pass a C function pointer
calc.run(f1);
// pass a C++98 functor
calc.run(F2());
// pass a C++11 stateless lambda
calc.run(+[](int a, int b) -> int { return a-b; });
// pass a C++11 stateful lambda
int k = 8;
calc.run([k](int a, int b) -> int { return a*b+k; });
}
You don't need to manually spell out any types, and you can pass function-like objects that can be stateful.
The power of C++11 comes from the && syntax. There's more to it than meets the eye. In run's parameter, F is a deduced type, and && is a universal reference. That means that, depending on the context, it acts either as an lvalue-reference we know from C++98, or as an rvalue-reference.
The + operator applied to the lambda stresses that it is in fact stateless. Its uses forces a conversion from the abstract lambda type to a C function pointer. The type of the +[](int,int)->int {...} expression is int(*)(int,int). The use of the + operator is not necessary, I've only used it to underline the statelessness.

Syntax error of a pointer to member function

Salutations
I'm trying to use the std::sort algorithms on specials objects.
I got a list to sort and a binary function which give me a comparison:
Interesting part of B.cpp
void B::FindClosest(vector<A*> list)
{
bool (B::*ptr)(A*,A*) = &B::Closer;
sort(list.begin(),list.end(),(this->*ptr));
// some use of this sorted list
}
bool B::Closer(A* lhs ,A* rhs)
{
if(Distance(this,lhs)<Distance(this,rhs))
{
return true;
}
else
{
return false;
}
}
And B.h :
class B : public A
public:
void FindClosest(vector<A*>);
bool Closer(A*,A*);
This seems pretty simple but i can't figure out why it's not working.
It seems to me that i'm doing something wrong on pointer to member function but cant find out what.
Here is the error msg :
agglomerate.cpp:32: error: invalid use of non-static member function
I've tried some other way to get things to work but nothing.
I'm not bound to pointer to member function, if you got a simple / different way to do this you're welcome.
Thanks a lot,
Azhrilla
You cannot use such thing, you should use std::bind or boost::bind or lambda for this case, since sort third parameter should be callable object, that receive two objects of type T.
With std::bind it will be
using namespace std::placeholders;
sort(list.begin(), list.end(), std::bind(ptr, this, _1, _2));
This line:
bool (B::*ptr)(A*,A*) = &B::Closer;
Gets a point to the member function B. To call this function you then need a class instance to call it on (the member function needs to know which conrete instance of class data it can access etc). For example
(this->*ptr)(lhs, rhs)
Calls the member function of this. If you did
B anotherB;
bool (B::*ptr)(A*,A*) = &B::Closer;
(anotherB.*ptr)(lhs, rhs)
That would call the B::Closer function but this time using anotherB and not this (assuming this was not 'anotherB')
I'm not sure what...
(this->*ptr)
...evaluates to?, but it is the problem
I think the problem is that you cannot give sort() the class instance and the member function pointer... you can only give it the member function pointer and so it has no class instance on which to call this function.
As ForEveR suggests, you could usde std::bind so that you can convert from a function withfour parameters, hls, rhs, class-instance, member-pointer. bind one to 'this' and one to the desired member function, so that the result is a function that just needs lhs and rhs.

Troubles with pointer to methods

I'm just learning C++ and I'm having difficulties regarding pointers to methods. Lets say:
class One {
public:
int Add (int a, int b) {return a+b;}
};
typedef int (One::*pAdd) (int, int);
class Other {
public:
int Next (pAdd funct, int c){ return funct (c, 1);}
};
int main (){
One one;
Other other;
other.Next(one.Add, 2);
return 0;
}
I have a number of problems, as reported by my MinGW. First, I'm not invoking funct correctly, as compiler insists on using .* or ->* . Have no idea how to incorporate this request and any help is welcomed. Now, I could solve my problems by making methods static to use c-style pointers or pass objects and invoke methods from within Next, but I want to understand pointers to methods. Basically, I'm puzzled why one.Add is not an acceptable input. Method to call is unambiguously defined (.Add) and conforms my typedef. Also, I'm providing instance of class (one) from typedef thus providing context in which method is to be executed. But compiler output looks like I didn't only miss the syntax, but like I missed the concept. So, how to pass pointer to method with object as context as a single argument?
The main problem here is that member functions are not associated with an object instance, they are just function pointers with a slightly different signature.
So, when you want to call a member function you need two things: a pointer to the member function and the object instance in which to call it.
I changed your code sample a bit:
#include <iostream>
class One {
public:
int Add (int a, int b) {return a+b;}
};
typedef int (One::*pAdd) (int, int);
class Other {
public:
int Next (One one, pAdd funct, int c){
return (one.*funct)(c, 1);
}
};
int main (){
One one;
Other other;
std::cout << other.Next(one, &One::Add, 2) << std::endl;
return 0;
}
And it works now. It can probably be improved a bit, but I think you can take it from here.
I recommend that you read Pointers to member functions section of the c++ faq lite, which explains this very well.
So, how to pass pointer to method with object as context as a single argument?
Using just member-function pointers, you can't. Although your syntax looks like something that should do that, it just isn't allowed. You need an object to apply the function to:
class Other {
public:
int Next (pAdd funct, One & o, int c){ return (o.*funct) (c, 1);}
}
int main (){
One one;
Other other;
other.Next(&One::Add, one, 2);
}
If you want to create a function object that calls a particular member function of a particular object, then one possibility is to use std::bind (or boost::bind if you can't use C++11 yet):
#include <functional>
class Other {
public:
int Next (std::function<int(int,int)> funct, int c){ return funct (c, 1);}
};
int main (){
One one;
Other other;
using namespace std::placeholders;
other.Next(std::bind(&One::Add, &one, _1, _2), 2);
}
or a lambda:
other.Next([&](int a, int b){return one.Add(a,b);}, 2);
Pointers to members need an instance to operate on. Essentially, they are functions which take an addition parameter which becomes the implicit this pointer. To call a function through a pointer to member for the current object you can use code like this:
(this->*funct)(c, 1);
(you'd access member variables similarly but without a function call).
The object you call the member on isn't part of the pointer to member. As a result you need to get it something like this:
&One::Add
This becomes more interesting if the member function is overloaded: in this case you need to provide a context from which the overload can be determined when taking the address. I tupically use a static_cast<>() for this:
static_cast<int (One::*)(int,int)>(&One::Add)
You have a bunch of problems here: one.Add is a member function and
you cannot just invoke it. You need to have a pointer to the class to
invoke it on as well. Also, you need to use the special operator.*
or operator->*. You can also not take the address of a bound member
function.
All in all, you should use a template and boost/std::bind to make
all this bearable or stay away from it.
Here is modified, working code:
class One {
public:
int Add (int a, int b) {return a+b;}
};
typedef int (One::*pAdd) (int, int);
class Other {
public:
int Next (One* one, pAdd funct, int c){ return (one->*funct)(c, 1);}
};
int main (){
One one;
Other other;
other.Next(&one, &One::Add, 2);
return 0;
}

mem_func and virtual function

I have the following classes:
class A
{
public:
virtual void myfunc(unsigned char c, std::string* dest) = 0;
};
class B : public class A
{
public:
virtual void myfunc(unsigned char c, std::string* dest);
};
void someOtherFunc(const std::string& str,A *pointerFunc)
{
std::string tmp;
for_each(str.begin(),
str.end(),
std::bind2nd(std::mem_fun(pointerFunc->myfunc), &tmp));
}
I get the following compilation error:
error: no matching function for call to \u2018mem_fun()\u2019
Do you know why?
You're looking for std::mem_fun(&A::myfunc).
EDIT: You can't use mem_fun at all here -- no overload of mem_fun allows you to make a two argument member function into a functor. You're going to have to use something like boost::bind/std::tr1::bind (If you have TR1)/std::bind (If you have C++0x) or you're going to have to write your own functor.
Note that even if mem_fun was able to do this sort of binding, then std::bind2nd would fail, because bind2nd expects a functor taking two arguments, and binding a member function pointer like this is going to produce a functor with three arguments.
You have a few ways around this:
Write your own functor that does what you want.
Write an explicit loop instead of std::for_each.
One of the not-yet-standard binder functions I mentioned above (and demonstrated in #David's answer)
Don't bother with the virtual function in the first place -- make your method accept a plain function pointer and implement things in terms of the function pointer. Of course this only works if myfunc doesn't depend on members of the class to which it belongs (in which case it shouldn't have ever been put into a class in the first place)
What you are trying to use here is use a pointer to a member function to apply a member function of another object to every object in the container. Apparently none of the adapters will work in this case. In that case the only solution is to write a special wrapper functor class for it.
Looking at the implementation behind of std::mem_fun you should be able to write your own:
EDIT (made it "human-readable")
template<class Result, class Ty, class Arg>
class mem_fun1_t : public binary_function<Ty*, Arg, Result>
{
private:
Result (Ty::*m_mf)(Arg);
public:
mem_fun1_t(Result (Ty::*mf)(Arg)) : m_mf(mf) { }
Result operator()(Ty* pLeft, Arg Right) const {
return ((pLleft->*m_mf)(Right));
}
};
Your declaration does not represent what you want to do.
try:
void someOtherFunc(const std::string& str)
{
std::string tmp;
B BInstance;
A* ptrToB = &BInstance;
for_each(str.begin(),
str.end(),
boost::bind(&A::myfunc, ptrToB, _1, &tmp));
}
this (or a variation of) should do what you want.