How to list.sort(memberFunction);? - c++

I'd like to use the sort function of std::list, and sort with the member function of "myClass" that contains a property I want to use while sorting.
struct node
{
int value;
}
class myClass
{
private:
bool _available;
public:
myClass();
~myClass();
private:
bool compare(const node &first, const node &second)
{
if (_available == true)
return (first.value < second.value);
else
return (first.value > second.value);
}
};
Then when I call : list.sort(myClass::compare);
I got : error: no matching function for call to ‘std::list<node>::sort(<unresolved overloaded function type>)’

The comparison function in problematic because you use a private member variable in it. That means you can't really use a static member function or a free-standing function or a lambda.
You also have a problem in that the comparison function is private, which means you have to sort the collection from inside a myClass object instance.
The first problem can be solved by using std::bind to bind the member function to a specific object instance. The second problem can be solved by making the function public (or by sorting from another member function inside the myClass class).
You can use std::bind like this:
// Definition of `list` here somewhere
myClass myObject;
list.sort(std::bind(&myClass::compare, &myObject));

Because myClass::compare is not a static method. You must make it static to pass it as a predicate for a sort. Or make it global. Also it must be public if it is to be a static class method.
typedef struct s_node
{
int value;
int t_node;
};
class myClass
{
private:
bool _available;
public:
myClass();
~myClass();
static bool compare(const t_node &first, const t_node &second)
{
if (_available == true)
return (first.value < second.value)
else
return (first.value > second.value)
}
};
OR
typedef struct s_node
{
int value;
int t_node;
};
class myClass
{
private:
bool _available;
public:
myClass();
~myClass();
};
bool compare(const t_node &first, const t_node &second)
{
if (_available == true)
return (first.value < second.value)
else
return (first.value > second.value)
}
And you could call it as:
list.sort( myClass:compare ); // first example
or
list.sort( compare ); // second example

Related

Polymorphic vector C++ – no matching member function for call to 'compare'

I have an abstract class Type and two inherited classes Type_A, Type_B. I have implemented some sort of comparisons using virtual functions. I would like to make a polymorphic vectors of pointers containing pointers to both Type_A and Type_B. Then I would like to pick two objects from those vectors and compare them, but I am getting the following error:
class Type {
public:
virtual bool compare(const Type_A &other) = 0;
virtual bool compare(const Type_B &other) = 0;
};
class Type_A : public Type {
string data;
public:
Type_A(string given_data) {
data = given_data;
}
bool compare(const Type_A& other) {
return (data > other.data);
}
bool compare(const Type_B& other) {
return false;
}
};
class Type_B : public Type {
public:
int data;
Type_B(string given_data) {
data = stoi(given_data);
}
bool compare(const Type_B& other) {
return (data > other.data);
}
bool compare(const Type_A& other) {
return false;
}
};
int main() {
vector<Type*> vec1;
vector<Type*> vec2;
Type_A test1("ab");
Type_B test2("ba");
vec1.push_back(&test1);
vec2.push_back(&test2);
cout << vec1[0]->compare(vec2[0]) << endl; //ERROR: no matching member function for call to 'compare'
}
There's two problems. One is that vec2[0] is a pointer type but compare expects regular objects. Other is that Type.compare expects either Type_A or Type_B object, not Type object. Do:
vec1[0]->compare(*(Type_B *) vec2[0])

adding functionality onto polymorphic tree in c++

I have a polymorphic tree and I'm trying to do add functionality like comparing two nodes without using RTTI like dynamic_cast The approach I'm taking is the visitor pattern.
The issue I'm having is that the visitor pattern isn't letting me operate on any parameters or getting return types out of the functions.
For example if I wanted to write a visitor that compares two nodes
class AbstractDispatch{
public:
virtual void visit(NodeFoo &operand) = 0;
virtual void visit(NodeBar &operand) = 0;
//...for all types.
};
class CompareVisitor{
public:
void visit(NodeFoo &operand) override;
//...
};
class SetVisitor{
public:
void visit(NodeFoo &operand) override;
//...
};
void CompareVisitor::visit(NodeFoo &operand){
//compare operand to what?
//get result of comparison how?
}
void SetVisitor::visit(NodeFoo &operand){
//set operand to what?
}
My current idea is to add other functions and members to the visitor classes. This would let me do something like this:
Base *object = new NodeFoo();
CompareVisitor compare;
compare.set_parameters(NodeFoo(/* */));
object->accept(compare);
bool result = compare.get_result();
I could set the parameters of the compare visitor and traverse the tree with it checking for the nodes and doing other such operations in this fashion.
Another solution would be to store node-type information in the node and do a get_type() check for safe-casting.
dynamic_cast is slow but if the node-type hierarchy is extremely simple could it be faster? Are there better design patterns for doing something like this?
You could write a visitor that compares the current node with the previous one.
class Node{...}
class NodeFoo : public Node {...}
class NodeBar : public Node {...}
class visitor{
public:
void visit( const NodeFoo& node ){
//First node: store relevant comparison information to private variables
if( foo == nullptr ){
foo = &node;
}
//Other nodes: Compare to the stored data and store comparison result
else {
...
}
}
void visit( const NodeBar& node ){
...
}
bool result() const{ return result; };
private:
bool result = false;
//variables for comparison, could be this simple but also a variant type
// or plain Node*
NodeFoo* foo = nullptr;
NodeBar* bar = nullptr;
}
You would use it like
Node node1;
Node node2;
Visitor v;
node1.accept( v );
node2.accept( v );
v.result();
Sure, this is a very basic implementation, you could use a plain Node* to store the first node, if you presume that alle visited nodes have the same type. You could also use a variant type or store the type as string... ( you know the type by the executed visit function )
If the Node lifetime is not sure, you can store some Node depending data, that you need for the comparisson instead of a pointer to the node.... there are hundreds of possibilities, this is just a small sketch of the basic framework
It can be done with double visit ( = two virtual calls) if you allow CompareVisitor to have a state. I don't think there's a way around that given your visitor API.
#include <iostream>
#include <string>
#include <vector>
#include <memory>
struct FooNode;
struct BarNode;
struct Visitor
{
virtual void visit(FooNode&)=0;
virtual void visit(BarNode&)=0;
};
struct Node{
virtual void accept(Visitor& v) = 0;
};
struct FooNode: public Node{
virtual void accept(Visitor& v) override { v.visit(*this);}
const char* print(){return "FooNode";}
};
struct BarNode: public Node{
virtual void accept(Visitor& v) override { v.visit(*this);}
const char* print(){return "BarNode";}
};
using ret_type=std::string;
//Feel free to specialize or overload
//Or create comparator class that allows partial specializations
template<typename Left, typename Right>
ret_type compare(Left &left, Right& right){
return std::string(left.print()) + "<=>" + right.print() + '\n';
}
//Compares (visited) and (rightNode)
class RightCompareVisitor : public Visitor {
public:
RightCompareVisitor(Node& right):rightNode(right){}
void visit(FooNode &left) override
{
visitRightNode(left);
}
void visit(BarNode &left) override
{
visitRightNode(left);
}
ret_type getRes() { return std::move(result);}
private:
template<typename Left>
void visitRightNode(Left& left){
struct CompareVisitor: Visitor
{
ret_type& result;
Left& left;
CompareVisitor(ret_type& result, Left& left):result(result), left(left){}
void visit(FooNode &right) override final{
result = compare(left, right);
}
void visit(BarNode &right) override final{
result = compare(left, right);
}
};
CompareVisitor v(result, left);
rightNode.accept(v);
}
ret_type result;
Node& rightNode;
};
//If you add this then you can always just use 'compare' to compare any two
//nodes.
template<>
ret_type compare<Node,Node>(Node& left, Node& right){
RightCompareVisitor rC{right};
left.accept(rC);
return rC.getRes();
}
int main()
{
std::vector<std::unique_ptr<Node>> nodes;
nodes.emplace_back(std::make_unique<FooNode>());
nodes.emplace_back(std::make_unique<BarNode>());
nodes.emplace_back(std::make_unique<FooNode>());
for(auto&& left : nodes)
for(auto&& right: nodes)
std::cout<<compare(*left,*right);
}
Add consts where you want. If you want RightCompareVisitor to be reused then use pointers for nodes.
Output:
FooNode<=>FooNode
FooNode<=>BarNode
FooNode<=>FooNode
BarNode<=>FooNode
BarNode<=>BarNode
BarNode<=>FooNode
FooNode<=>FooNode
FooNode<=>BarNode
FooNode<=>FooNode

How to add handle as a class member, where class is used for template of heap?

Consider the simple example:
#include <boost/heap/fibonacci_heap.hpp>
class MyClass;
struct compare_distances
{
bool operator()(const MyClass* n1, const MyClass* n2) const
{
return n1->distance > n2->distance;
}
};
typedef boost::heap::fibonacci_heap<MyClass*, boost::heap::compare<compare_distances> > fib_heap;
class MyClass
{
public:
string name;
double distance;
fib_heap::handle_type handle;
};
I want to have the access to handle of object of MyClass at heap in this manner. So I forward declare MyClass. But compiler says:
error: invalid use of incomplete type ‘const class MyClass’ (error for return line in compare_distances).
How to fix it?
It is necessary to implement a convenient network of objects such as:
class MyClass
{
public:
string name;
double distance;
fib_heap::handle_type handle[4]; // handles for other objects of MyClass
};
This compiles if you just declare the comparator functor's operator() before MyClass and you define it after the class definition like this:
class MyClass;
struct compare_distances
{
inline bool operator()(const MyClass* n1, const MyClass* n2) const;
};
typedef boost::heap::fibonacci_heap<MyClass*, boost::heap::compare<compare_distances> > fib_heap;
class MyClass
{
public:
string name;
double distance;
fib_heap::handle_type handle;
};
bool compare_distances::operator()(const MyClass* n1, const MyClass* n2) const
{
return n1->distance > n2->distance;
}
Note that I've added inline to the function to avoid linker errors. (Member functions defined in a struct are implicitly inline.)

std::vect sorting with member variable

I'm stuck with this piece of code:
class MyObject
{
public:
int value;
}
class MyClass
{
private:
btAlignedObjectArray<MyObject*> m_objects;
public:
int comp (MyObject *a, MyObject *b)
{
return calculateTheNewValue(a->value) < calculateTheNewValue(b->value);
}
void doSort()
{
m_objects.quickSort(comp);
}
//edit: this member function is needed to do the sorting
int calculateTheNewValue(int v)
{
// do some calculation using other members variables, not necessarily m_objects
}
};
It doesn't compile because comp is a non static member function.
comp cant be static, because it needs to access the member variable m_objects.
Also it would defeat the encapsulation of m_objects to have a static function and call it like this
MyClass::doSort(myClass.m_objects)
Edit
This is the declaration of btAlignedObjectArray
http://bulletphysics.org/Bullet/BulletFull/btAlignedObjectArray_8h_source.html
Line 365 has the declaration or quicksort
If you need to make comp into a binary function, then wrap it in a functor. If you can use C++11, then use a lambda:
m_objects.quickSort([&](MyObject * lhs, MyObject * rhs) {
return this->comp(lhs,rhs)
});
If you can't use C++11, then make a functor class with similar behavior.
struct compare
{
MyObject & obj_;
compare(MyObject& obj) :obj_(obj) {}
bool operator()(MyObject * lhs, MyObject * rhs) const {
return obj_.comp(lhs,rhs);
}
};
...
void doSort()
{
m_objects.quicksort(compare(*this));
}

Comparator that requires access to private members of class

Basic structure of my code is
class Foo{
vector<string> _lines;
vector<int> _n;
public:
...
bool Comp(int i, int j){
return something that depends on _lines;
}
...
void doSomething(){
std::sort(_n.begin(), _n.end(), Comp);
}
...
};
But I get
error: no matching function for call to
‘sort(std::vector<unsigned int>::iterator,
std::vector<unsigned int>::iterator, <unresolved overloaded function type>)
How can I resolve this problem WITHOUT COPYING THE VECTORS? (because these vectors are very very big 17179508 strings to be precise).
std::sort expects a binary predicate taking two ints in this case. A member function takes an implicit first parameter, so in all Foo::Comp takes three parameters. You could pass a non-member function, or a static member function, but neither of these would have access to Foo's data members. The simples way is to use std::bind to bind this to the first parameter of the member function:
#include <functional> // for std::bind
#include <vector>
#include <algorithm>
class Foo{
vector<string> _lines;
vector<int> _n;
public:
...
bool Comp(int i, int j){
return something that depends on _lines;
}
...
void sort(){
using namespace std::placeholders;
std::sort(_n.begin(), _n.end(), std::bind(Comp, this, _1, _2));
}
...
};
The most obvious initial suggestion is to aggregate your int and string into a struct or std::pair, have a single vector with the aggregate in it, and then sort that vector of aggregates.
But if the two vectors are in fact independent, I would suggest using an external predicate, instead of your Comp method:
struct Comp
{
explicit Comp(vector<string>& lines) : lines_(lines) { }
bool operator()(int i, int j) const
{
return something that depends on lines_;
}
vector<string>& lines_;
};
Then call it:
void doSomething()
{
std::sort(_n.begin(), _n.end(), Comp(_lines));
}
What about using your object as the comparator itself. This compiles on gcc 4.6:
class Foo{
std::vector<std::string> _lines;
std::vector<int> _n;
public:
bool operator()(int i, int j){
return false;
}
void doSomething(){
std::sort(_n.begin(), _n.end(), *this);
}
};
Edit:
Turns out that was not such a good idea, copying an object with 17M strings would incur a huge penalty. A nested class, taking a pointer, could be used instead. That would also allow us to have different comparators:
class Foo
{
std::vector<std::string> _lines;
std::vector<int> _n;
class Bar
{
public:
Bar( const Foo * foo ) : _foo( foo ) {}
bool operator()( int i, int j )
{
act on _foo->_lines
}
private:
const Foo * _foo;
};
public:
void doSomething(){
std::sort(_n.begin(), _n.end(), Bar(this));
}
};