C++ sort vector using non-static member function - c++

I have a class called Sorter. It has two public items.
int type variable choice
member function called compare with a int type return value that accepts two objects as parameter.
I tried creating an instance of Sorter while passing choice with a value to the constructor,
Then i wanted to use C++ sort function to sort a vector. and to pass the member function compare of the instance i created.
The compare member function uses the variable choice to decide the sorting mechanism.
But i was not able to get the pointer to the member function compare of an instance of Sorter.
Could someone advice me on this?

If you can change the structure of your Sorter class, you could make it a function object by defining operator () like this:
bool Sorter::operator ()(const MyObject &o1, const MyObject &o2) {
// return true if o1 < o2
}
Then you can just pass an instance of your Sorter class to std::sort.

Unfortunately, the standard library is a bit lacking in combinators for things like this. However, boost::lambda can do the job:
#include <boost/lambda/bind.hpp>
namespace l = boost::lambda;
struct foo {
bool bar(char, char);
};
void test(foo *pFoo) {
char a[2] = {0};
std::sort(a, a+1,
l::bind(&foo::bar, pFoo, l::_1, l::_2));
}

Related

How to use a static method as a callback in c++

I have a comparison/ordering function that relates to a class. I can use it if I define it as a separate closure object. I would like to make it into a static method of the class it operates on so it is tidier. I guessed how to do this but I get an error that I can't interpret.
Generally I would like to know how to treat static methods as callable objects.
Minimal related example code (not working):
#include <set>
class MyClass {
// More code here
static auto compare(MyClass a, MyClass b) {
return a < b;
}
};
int main() {
std::set<MyClass, decltype(MyClass::compare)> s(MyClass::compare);
return 0;
}
Update, I'm not sure if my example confused the issue, so I updated it.
Couple of issues:
compare is private, make it public.
One must use & to get the address of functions.
#include <set>
class MyClass {
public:
static auto compare(int a, int b) {
return a < b;
}
};
int main() {
std::set<int, decltype(&MyClass::compare)> s(&MyClass::compare);
return 0;
}
Make the function public, and add & in decltype:
std::set<int, decltype(&MyClass::compare)>
I wouldn't consider this to be "tidier" though.
A functor occupies 0 bytes when used as a std::set comparator. But a function pointer (as in your example) occupies 4 or 8 bytes. It also forces you to pass the function to the set's constructor.
Using a function pointer this way only makes sense if you want to switch between different comparators at runtime.
If you do want a pointer, the class itself is unnecessary. You might as well use a free function.

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));
}

Get the name of an overloaded function passed as an argument at run-time

Assume all includes are defined, please go through the code structure defined below.
std::unordered_map<std::string, void*> callbackReg;
class A
{
public:
void foo(int a)
{
//impl
}
void foo(int a, int b)
{
//impl
}
void foo(int a, double d)
{
//impl
}
};
template<class Instance , typename Function>
void register_func(Instance& obj, Function func)
{
/* have to store function name as the key and
- pointer to raw member function pointer as the value,
- in callbackReg Map */
// ---> Point B
}
int main(int argc, const char * argv[])
{
A a;
register_evt(a, &A::foo); //---> point A
system("Pause");
}
Problems and Discussions
# Point A how to resolve function name scope resolution issue which means how to call a overloaded function/pointer to such function ? without inline static cast since it makes bit ugly and messy.
# Point B assume we have fixed overload name resolutuin issue and now we have to store member funtion name and its pointer value in callbackReg map.
I know may this could bad cumbersome approach but, is this feasible in C++? or else is there any way to store raw memeber funtion pointers with some other key-value in order to use them as callbacks.Since at debug time,debugger already knows what is the function name passed as register_func template fucntion argument.
Please look at the image attached.
Therefore,simply, how can we implement callback register/unregister scenario using only raw member/non-member function pointers?
(Please if the solution or methodology is a cross-platform approach that would be grateful, at least Win32 based)
You can use boost backtrace:
boost::stacktrace::frame provides information about functions. You may construct that class from function pointer and get the function name at runtime

Returning an object which is defined by another local object

I am wondering how to make a function return an object that is dependent of another object or pointer which does not exist outside the function. The situation is the following:
To sort a std::map there is a custom comparator function declared inside a class Object. This function must be a static member of a class or a global function in order to be passed to std::map:
static bool RenderOrderComparator(const Object *Obj, float a, float b);
This function must access some member of an instance of Object to compare two given floating point numbers correctly (non-trivial). Now I want to have another function which is used at several places in the respective unit to do the sorting:
X Object::SortInstances(const Camera &Cam)
{
auto comp = std::bind(RenderOrderComparator, this, std::placeholders::_1, std::placeholders::_2);
std::map<float, const ObjectTransformation &, decltype(comp)> SortedInstances(comp);
// ... do some stuff and fill the map
return SortedInstances;
}
The idea here was to use std::bind to bind this to the comparator function in order to access the required member. My question is now what do I have to write in the place of X? What is the type of the map I am actually intending to return? I tried something like
std::map<float, const ObjectTransformation &, decltype(std::bind(Object::RenderOrderComparator, this, std::placeholders::_1, std::placeholders::_2))>
which logically cannot work because this is not known outside the definition of the function. Also I played - unsuccessfully - with std::result_of. Do you have any solution for that problem?
I am looking foreward to your help.
Yours Julian
This function must be a static member of a class or a global function in order to be passed to std::map
Where did this requirement come from? std::map supports comparators that are not functions, but objects with operator() a.k.a. functors.
struct RenderOrderComparator {
Object const * scene_or_whatever;
bool operator() ( float a, float b ) {
return … ;
}
};
Use RenderOrderComparator as the third template argument to std::map. There should be no need for std::bind, which as it happens only produces such an object with an operator() member.

How do you save the function from a function pointer as a class' member function?

Basically, I have a templated class that runs some algorithm, and that algorithm needs a similarity(T t1, T t2) function that returns a double defining how similar two objects of type T are. This similarity function varies greatly depending on what T is defined as, so the caller of this class needs to define the similarity function. I assume a function pointer is in order, but how do I save a function from a function pointer as a member function for use in the algorithm?
That is, I want to pass in similarity(T t1, T t2) in the class' constructor and be able to call that as a member function throughout the class. How do I do that? Thanks
You can't add member functions to a class at runtime.
You could write a member function that calls the supplied function via the function pointer:
class MyClass {
typedef double (*similarity_fn_type)(T t1, T t2);
similarity_fn_type similarity_fn;
public:
MyClass(similarity_fn_type ptr) : similarity_fn(ptr) {}
double similarity(T t1, T t2) {
return similarity_fn(t1, t2);
}
};
Alternatively, you could make the similarity_fn member public. The syntax for calling it would make it look like a member function, but you might not consider it to be great encapsulation.
There are cleaner, object-oriented ways to do that. One of them is to pass an object with that function, similar to how Java allows reimplementing comparisons with the Comparator class. This implies the creation of a base class (with that function as purely virtual) and a subclass for each implementation of similarity().
In your case, you may find more useful the solution C++11 takes for implementing functions for comparing and hashing. It involves creating special function objects. See std::less and std::hash for examples.
I do something similar to abstract away the process of iterating through a collection. I use a predicate to specify the actual search criteria:
void MyClass::Copy(Class &destination, const Class &source, const std::function<bool (const Effect&)> &predicate)
{
for (size_t i = 0; i < Effect::Max; ++i)
{
const Effect *const pEffect = source.GetEffect(i);
if (predicate(*pEffect))
{
// Do something
}
}
}
void MyClass::CopyInner(Class &destination, const Class &source)
{
this->Copy(destination, source, [](const Effect &effect)
{
return effect.IsInner();
});
}
Note: This uses some C++11 features.
Define a const function pointer member of the appropriate type:
typedef double(*Similarity)(T, T);
const Similarity similarity;
Let the constructor accept a function of that type:
Class(Similarity f) : similarity(f) {}
Then calling the function has the same syntax as calling an ordinary member function:
frobnicate(similarity(foo, bar));
And if the member is public, it cannot be changed out from under you because it’s const.