I'm trying to use the Boost d_ary_heap but I cannot figure out how to get the handle for a pushed element. In my case, I will need to update the value in a later iteration, so I need that handle. I was able to do it with the Fibonacci heap but in this case it looks much more complex.
This is what I have so far:
struct compare_cells_d_ary {
inline bool operator()
(const myType * c1 , const myType * c2) const {
return c1->getValue() > c2->getValue(); // I want a min heap.
}
};
class MyHeap {
typedef typename boost::heap::d_ary_heap<const myType *, boost::heap::mutable_<true>, boost::heap::arity<2>, boost::heap::compare<compare_cells_d_ary>>::handle_type handle_t;
protected:
boost::heap::d_ary_heap<const myType *, boost::heap::arity<2>, boost::heap::mutable_<true>, boost::heap::compare<compare_cells_d_ary>> heap_;
std::vector<handle_t> handles_; // I store the handles in an specific order.
public:
/****/
void push (const myType * c) {
handles_[c->getIndex()] = heap_.push(c);
}
/****/
};
The push function is how I use it in the Fibonacci heap, which returns a handle_type. But in this case I cannot understand what it is supposed to return (http://www.boost.org/doc/libs/1_55_0/doc/html/boost/heap/d_ary_heap.html#idp52218904-bb)
Any help in how to get the handle when pushing is welcome! Thanks.
Since you declared your heap as mutable, the push operation is supposed to return the handle_t you typedefed as the handle_type:
mpl::if_c< is_mutable, handle_type, void >::type push(value_type const & v);
In the respect of obtaining the handle, your code is fine. To simplify a bit to make it clearer:
void push (const myType * c) {
handle_t handle = heap_.push(c);
handles_[c->getIndex()] = handle;
}
As a side-note, you should have a typedef for the heap instead of repeating it in the declarations, and the typename is superfluous (at least in the snippet you posted in the question.)
Related
I wonder how is the most convenient way to have a sorted set, a set of pointers to objects, like
std::set<myClass*> mySet;
I want this set to be sorted by myClass::someProperty (say, an int).
Should I overload operator < in myClass? I'm not sure if it will work, because it's not a set of myClass, but a set of pointers.
How can I define a compare function?
Thank you very much.
You need to define a type (or a function) that dereferences the pointers and compares the attributes of the objects they point at, something on this general order:
class myClass {
int value;
public:
myClass(int i = 0) : value(i) {}
struct cmp {
bool operator()(myClass *const &a, myClass *const &b) const {
return a->value < b->value;
}
};
};
We they define the set something like this:
std::set<myClass*, myClass::cmp> mySet;
My advice, however, would be to store objects instead of pointers (if possible).
You can also specialize std::less for your myClass* as given below and then no need to pass comparator while creating set:
namespace std {
template<>
struct less<myClass*>
{
bool operator()(const myClass* k1, const myClass* k2) const
{
// Some code ...
}
};
}
I have the following struct
struct MyClass {
int myInt;
std::map<int, int> myMap;
};
I want to use unordered_set<MyClass*, PointedObjHash, PointedObEq> but I can't find a valid way to declare PointedObEq.
I tried
struct PointedObjHash {
size_t operator() (MyClass* const& c) const {
std::size_t seed = 0;
boost::hash_combine(seed, c->myInt);
boost::hash_combine(seed, c->myMap);
return seed;
}
and I hope it is fine, but I can't find a way to declare PointedObjEq
--- EDIT ---
If declare operator== inside the class debug never breaks, but I think 'cause MyClass == MyClass* never happens...
struct MyClass {
...
...
bool operator==(MyClass* const& c) {
return this->myInt == c->myInt & this->myMap == c->myMap;
}
If declare operator== inside the class debug never breaks, but I think 'cause MyClass == MyClass* never happens...
The unordered_set needs to use operator== (or PointedObjEq) to double-check the results of the hash function. The hash provides approximate equality, the equality function is used to weed out false positives.
If you've tested adding the same value to the set twice, then you've tested the equality function. To be sure, of course, you can have it print something to the console.
Since it's impossible to define an operator== function with two pointer operands, the PointedObjEq class will be necessary. Note that it takes a MyClass const * on both sides. Also, there's no need to use a reference to a pointer.
So,
struct PointedObjEq {
bool operator () ( MyClass const * lhs, MyClass const * rhs ) const {
return lhs->myInt == rhs->myInt
&& lhs->myMap == rhs->myMap;
}
};
This should do:
struct PointedObEq {
bool operator()(MyClass const * lhs, MyClass const * rhs) const {
return lhs->myInt == rhs->myInt && lhs->myMap == rhs->myMap;
}
};
The reason why your solution does not work is because you have effectively written a mechanism to compare a MyClass with a MyClass*, when you actually need something to compare a MyClass* with a MyClass*.
P.S.: My original answer passed the pointers by const&. Thinking about it, that's a strange coding style, so I changed it to pass the pointers by value.
typedef MyClass* PtrMyClass;
struct PointedObjCompare
{ // functor for operator==
bool operator()(const PtrMyClass& lhs, const PtrMyClass& rhs) const
{
// your code goes here
}
};
std::unordered_set < MyClass*, PointedObjHash, PointedObjCompare > myset;
This question already has answers here:
Is casting std::pair<T1, T2> const& to std::pair<T1 const, T2> const& safe?
(3 answers)
Closed 8 years ago.
This code demonstrates the problem I'm trying to solve:
#include <map>
class Point
{
public:
float m_x;
float m_y;
};
typedef std::set<Point *> PointSet;
typedef std::set<const Point * const> ConstPointSet;
float GetMinimumRange(const ConstPointSet &pointSet)
{
float minimumRange(0.0f);
// find the smallest distance between any pair of points in the set
return minimumRange;
}
float GetMinimumRangeWrong(const PointSet &pointSet)
{
PointSet::iterator first(pointSet.begin());
Point * point(*first);
point->m_x = 42.0f; // I want to prevent this
return 0.0f;
}
class PointSet_
{
public:
std::set<Point *> m_pointSet;
float GetMinumumRange() const
{
PointSet::iterator first(m_pointSet.begin());
Point * point(*first);
point->m_x = 42.0f; // I want to prevent this
return 0.0f;
}
};
void test()
{
PointSet myPointSet;
// Add some points to my set
// This fails because the compiler states it can't convert from PointSet to ConstPointSet.
//float minimumRange1(GetMinimumRange(myPointSet));
// reinterpret_cast<> is the only cast that works here, const_cast fails with the same
// complaint as the line above generates
ConstPointSet *myConstPointSet(reinterpret_cast<ConstPointSet *>(&myPointSet));
float minimumRange1(GetMinimumRange(*myConstPointSet));
float minimumRange2(GetMinimumRangeWrong(myPointSet));
}
I want to create a routine that takes a PointSet, evaluates the minimum range between any pair of Points in the set, but that it guarantees that it won't modify the PointSet passed to it in any way at all. It can't modify the members of any referenced Point, it can't change the pointers themselves, nor can it add or remove members from the set
The issue is that the compiler correctly views PointSet and ConstPointSet as different types because of the difference of const qualifiers of the inner type, and therefore refuses to cast between them, even though I'm only adding const qualifiers.
I tried creating a class to contain a PointSet, and creating a const member function, but even in there it allows modification to one of the inner Points. At least MSVC will compile that without complaint. I'll confess I was quite surprised about this.
The only way I've found that works is to use a reinterpret_cast<> to convert a pointer to a PointSet to a pointer to a ConstPointSet. The standard does note that reinterpret_cast<> can be used to add const qualifiers, but does that apply in this case?
If not, is there any way to do what I want? I realize that good code discipline can be used to ensure that GetMinimumRange() doesn't modify the passed PointSet, but I'd like to get those const qualifiers in there for two reasons.
They will ensure that if anyone ever modifies GetMinimumRange() they can't cause it to modify the PointSet.
It will allow the compiler to optimize over the call to GetMinimumRange(). In the absence of the const qualifiers, no assumptions can be made at the calling site regarding values that could be cached across the call, thus possibly leading to redundant fetches of data.
There is no straightforward way, because constness does not propagate through pointers. In a const PointSet, it's the pointers themselves that are const, not the objects they point to. And, like you've discovered, const Point * is a different type from Point *, so std::set<const Point *> is a different type from std::set<Point *>.
I don't like the reinterpret_cast of a STL structure. That is scary to me. STL does all kinds of optimizations based on the type of template parameters. std::vector<bool> being an extreme example. You'd think that std::set<T *> and std::set<const T *> would be laid out the same because they are both pointers, but I wouldn't assume so until I read it in the Standard.
If it were a structure I had written myself, and I could easily verify that the cast would work, it would be less scary but still ugly.
You could write a wrapper class that holds a reference to a std::set<Point *> but only allows const access to its pointed-to Points via iterators. If the pointers are guaranteed to be non-null, your iterator can dereference the points directly. I've written it here as a template:
template <typename T>
class PointerSetViewer
{
public:
PointerSetViewer(std::set<T *> const &set) : set(set) {}
struct iterator : public std::iterator<std::forward_iterator_tag, T const>
{
iterator(typename std::set<T *>::const_iterator it) : it(it) {}
T const &operator*() const { return **it; }
T const *operator->() const { return *it; }
iterator &operator++() { ++it; return *this; }
bool operator==(iterator other) { return it == other.it; }
bool operator!=(iterator other) { return it != other.it; }
private:
typename std::set<T *>::const_iterator it;
};
iterator begin() { return iterator(set.cbegin()); }
iterator end() { return iterator(set.cend()); }
private:
std::set<T *> const &set;
};
It's bulky, but it accomplishes your goals without doing anything risky:
float GetMinimumRangeWrong(PointerSetViewer<Point> &pointSet)
{
PointerSetViewer<Point>::iterator first(pointSet.begin());
first->m_x = 42.0f; // does not compile
}
Also if you're using C++11, you can get some nice range-based for loops:
template <typename T>
PointerSetViewer<T> view_set(std::set<T *> const &set) {
return PointerSetViewer<T>(set);
}
for (Point const &p : view_set(myPointSet)) {
// whatever...
}
Baroque? Yes, but if one piece of baroque library code lets you write 100 pieces of beautiful application code with better type checking, it's probably worth it.
Edit: this doesn't work for set. As pointed out in comments, a non-const set is defined to hold const T, so there is actually nothing we can do.
At this stage I don't see a viable solution other than making PointSet_ actually wrap the set properly, i.e. have the set be private and be careful in your public functions.
Here is a solution I came up with; make the set contain a little wrapper which will propagate the const-ness of itself onto the pointer.
I would have thought there would be a pre-existing class that does this, but none of the std smart pointer classes seem to.
#include <iostream>
#include <set>
template<typename T>
struct qualifier_ptr
{
T *operator->() { return ptr; }
T const *operator->() const { return ptr; }
operator T*() { return ptr; }
operator T const*() const { return ptr; }
qualifier_ptr(T *p): ptr(p) {}
private:
T *ptr;
};
struct Point
{
float m_x;
float m_y;
};
struct PointSet
{
typedef std::set< qualifier_ptr<Point> > SetType;
SetType points;
float foo() const
{
//Point *p = *points.begin(); // error
Point const *p = *points.begin(); // OK
return 0;
}
};
int main()
{
PointSet ps;
PointSet const &cps = ps;
ps.foo(); // OK
cps.foo(); // OK
}
I normally don't like to use conversion operators but it seems appropriate here.
As you stated in the comments that the set is built only once per session, I'd suggest just creating the ConstPointerSet by making a copy:
void test()
{
PointSet myPointSet;
// Add some points to my set
ConstPointSet myConstPointSet{ begin(myPointSet), end(myPointSet) };
float minimumRange1(GetMinimumRange(myConstPointSet));
}
Or wrapp it into a function:
ConstPointSet toConst(const PointSet& pSet){
return ConstPointSet{ cbegin(pSet), cend(pSet) };
}
If you don't need the semantics of a set I'd recommend using a std::vector instead, which is much more efficient to copy or traverse.
Is it possible to call operator[] with out using * when I have a pointer to the class ?
class MyClass
{
public:
void operator[](int n)
{
cout<<"In []";
}
};
int main()
{
MyClass *a=new MyClass;
(*a)[2];//work
a[2];//It just do some pointer arithmetic ...too bad :((
}
Yes, you should be able to use the -> operator, like this:
a->operator[] (2);
Demo on ideone.
If all you need is eliminating the asterisk, this should do the trick. If you are aiming for a better readability, this isn't of much help - you need to either avoid the pointer, or to use a regular member function:
class MyClass
{
public:
void operator[](int n)
{
cout<<"In []";
}
// Add a regular function for use with pointers
// that forwards the call to the operator[]
void at(int n) { (*this)[n]; }
};
Now you can write a->at(2);
(Demo on ideone).
template<typename LHS> struct at_lhs_t { LHS lhs; };
static struct at_t {} at;
template<typename LHS>
at_lhs_t<LHS> operator%( LHS&& lhs, at_t )
{ return {std::forward<LHS>(lhs)}; }
template<typename LHS, typename RHS>
auto operator%( at_lhs_t<LHS>&& lhs, RHS&& rhs )
->decltype( (std::forward<LHS>(lhs.lhs))->operator[](std::forward<RHS>(rhs)) )
{ return ( (std::forward<LHS>(lhs.lhs))->operator[](std::forward<RHS>(rhs)) ); }
class MyClass
{
public:
void operator[](int n)
{
std::cout<<"In []";
}
};
int main()
{
MyClass *a=new MyClass;
a %at% 2;
}
live example, but this is probably not what you want either.
In practice, just use the *. The * (as well as ->s) help remind you that the left hand side must be first checked for validity before it can be used in most contexts. After you check that your pointer is valid, you can dereference and store it in a reference for the duration of the current scope, and use [] to your heart's content.
The (*a) brackets get to be a bit annoying. On the other hand, possibly you should also avoid using pointers as much: modern C++ has moved away from using pointers, and would rather wrap things in smart pointers or pImpl wrappers and store the data in value-semantic types.
Then you only deal with pointers inside your smart pointer storage types, and when you want reseatable indirection to resources held elsewhere. Your nice and pretty pImpl wrappers are used more often, and they act like values even if most of their state is held dynamically.
i have a priority queue and i have defined like this:
priority_queue<Node*,vector<Node*>,greater<Node*>> myQueue;
i have to add to queue on the basis of a parameter param and i have overloaded it like this
bool Node::operator>(const Node& right) const
{
return param>right.param;
}
since the overload function doesnt take a pointer object, how should i change it so that my overloaded function is called.
i am adding to queue this way:
Node *myNode
myQueue.add(myNode);
i cant pass the myNode without making as pointer object.
please guide ..
#Sellibitze
i have done something like this
template<typename Node, typename Cmp = std::greater<Node> >
struct deref_compare : std::binary_function<Node*,Node*,bool>
{
deref_compare(Cmp const& cmp = Cmp())
: cmp(cmp) {}
bool operator()(Node* a, Node* b) const {
return cmp(*a,*b);
}
private:
Cmp cmp;
};
typedef deref_compare<Node,std::greater<Node> > my_comparator_t;
priority_queue<Node*,vector<Node*>,my_comparator_t> open;
i am filled with errors.
You need to write your own functor for the comparison because you can't overload operator> for pointers. So, instead of greater you would be using your own dedicated class with the appropriate function call operator. This could be even done generically.
template<typename T, typename Cmp = std::less<T> >
struct deref_compare : std::binary_function<T const*,T const*,bool>
{
deref_compare(Cmp const& cmp = Cmp())
: cmp(cmp) {}
bool operator()(T const* a, T const* b) const {
return cmp(*a,*b);
}
private:
Cmp cmp;
};
typedef deref_compare<Node,std::greater<Node> > my_comparator_t;
Edit1: I just realized you could do it even more generically, with iterators instead of pointers. ;-)
Edit2: If you're not comfortable with the template and don't need this generalization you could just as well use
struct my_node_ptr_compare
{
bool operator()(Node const* a, Node const* b) const {
return *a > *b;
}
};
priority_queue<Node*,vector<Node*>,my_node_ptr_compare> foo;
Set up the operator>() as a friend-of-Nodes function taking two Nodes.
Use the friend keyword.
Some refs:
http://www.cprogramming.com/tutorial/friends.html
http://msdn.microsoft.com/en-us/library/465sdshe(VS.80).aspx
Edit: This won't work in the pointer case, but will work in the regular Nodes case.
The simplest way would be to implement a compare function that takes Node pointers as its parameters, like this:
bool nodePtrGreater(Node const *a, Node const *b) {
return *a > *b;
}
This function should use the operator> of your Node class properly.
[edit] The old version didn't define the queue correctly.
Create your priority queue like this:
priority_queue<Node*,vector<Node*>, bool(*)(Node const *, Node const *)> myQueue(nodePtrGreater);