Using fibonacci_heap results in a compilation error:
struct Less: public binary_function<Node*, Node*, bool>
{
bool operator()(const Node*& __x, Node*& __y) const
{ return __x->time < __y->time; }
};
boost::fibonacci_heap<Node*, Less >* m_heap;
then
Less* ls = new Less;
m_heap = new boost::fibonacci_heap<Node*, Less >(1000, (*ls));
Any attempt to run m_heap->push(n) results in
no match for call to ‘(TimeSync::Less) (TimeSync::Node* const&, TimeSync::Node*&)’
UnmanagedUtils/Trading/Simulation/TimeSync.h:50: note: candidates are: bool TimeSync::Less::operator()(const TimeSync::Node*&, TimeSync::Node*&) const
/usr/local/include/boost-1_35/boost/property_map.hpp: In function ‘Reference boost::get(const boost::put_get_helper<Reference, PropertyMap>&, const K&) [with PropertyMap = boost::identity_property_map, Reference = unsigned int, K = TimeSync::Node*]’:
Change the signature to operator()(Node * const &, Node * const &) const.
Related
I've got a template class containing a priority queue of other classes, I need to use the priority overloader to call the individual class overloaders to compare based on the individual classes preferences (in this case it's age, in another class it could be price.
I've got absolutely no doubt that I've implemented the operator overloading incorrect so would appreciate the advice.
For example
#include <iostream>
#include <queue>
#include <string>
using namespace std;
class Animal {
public:
Animal();
Animal(string t, int a);
int get_age()const;
bool operator< ( Animal& b) const;
void display()const;
private:
string type;
double age;
};
void Animal::display() const
{
cout << "Type: " << type << " Age: " << age;
}
int Animal::get_age() const
{
return age;
}
Animal::Animal(){}
Animal::Animal(string t, int a)
{
type = t;
age = a;
}
bool Animal::operator< ( Animal& b) const
{
return b.get_age();
}
template<typename T>
class Collection {
public:
Collection();
Collection(string n, string d);
void add_item(const T& c);
private:
priority_queue <T> pets;
string name; // Name of the collection
string description; // Descriptions of the collection
};
template<typename T>
Collection<T>::Collection(){}
template<typename T>
Collection<T>::Collection(string n, string d)
{
name = n;
description = d;
}
template<typename T>
bool operator<(const T& one, const T& two)
{
return one.operator<(two);
}
template<typename T>
void Collection<T>::add_item(const T& c)
{
pets.push(c);
}
int main(){
Animal p1("Dog", 10);
Animal p2("Cat", 5);
Animal p3("Turtle", 24);
Collection<Animal> P("Pets", "My Pets");
P.add_item(p1);
P.add_item(p2);
P.add_item(p3);
cout << endl;
return 0;
}
I get this error and I'm not sure what I need to do to fix it. I've got to keep the class overloader as the single variable (Animal& b).
task.cpp: In instantiation of 'bool operator<(const T&, const T&)
[with T = Animal]':
c:\mingw-4.7.1\bin../lib/gcc/mingw32/4.7.1/include/c++/bits/stl_function.h:237:22:
required from 'bool std::less<_Tp>::operator()(const _Tp&, const _Tp&)
const [with _Tp = Animal]'
c:\mingw-4.7.1\bin../lib/gcc/mingw32/4.7.1/include/c++/bits/stl_heap.h:310:4: required from 'void std::__adjust_heap(_RandomAccessIterator,
_Distance, _Distance, _Tp, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator > >; _Distance = int; _Tp = Animal; _Compare =
std::less]'
c:\mingw-4.7.1\bin../lib/gcc/mingw32/4.7.1/include/c++/bits/stl_heap.h:442:4: required from 'void std::make_heap(_RandomAccessIterator,
_RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator > >; _Compare = std::less]'
c:\mingw-4.7.1\bin../lib/gcc/mingw32/4.7.1/include/c++/bits/stl_queue.h:393:9: required from 'std::priority_queue<_Tp, _Sequence,
_Compare>::priority_queue(const _Compare&, const _Sequence&) [with _Tp = Animal; _Sequence = std::vector >; _Compare = std::less]' task.cpp:57:45: required from 'Collection::Collection(std::string, std::string) [with T = Animal;
std::string = std::basic_string]' task.cpp:79:43: required
from here task.cpp:66:30: error: no matching function for call to
'Animal::operator<(const Animal&) const' task.cpp:66:30: note:
candidate is: task.cpp:36:6: note: bool Animal::operator<(Animal&)
const task.cpp:36:6: note: no known conversion for argument 1 from
'const Animal' to 'Animal&' task.cpp: In function 'bool
operator<(const T&, const T&) [with T = Animal]':
Your comparison
bool Animal::operator< ( Animal& b) const
{
return b.get_age(); // returns true always unless age == 0
}
is no comparison and it should take a const parameter. You should have something like
bool Animal::operator< (const Animal& b) const
// ^----------------------- const !
{
return get_age() < b.get_age();
}
Btw you dont need to use a member operator< for the priority queue. Especially if you want to sort objects in different ways I would recommend to not use it, but pass a lambda to the priority_queue. See eg here for an example.
Both of your overloads of < are problematic
bool Animal::operator< ( Animal& b) const
the Animal should also be const. You also need to compare both parameters, otherwise things (such as your priority_queue) that expect < to provide an ordering will have undefined behaviour.
You don't use anything non-public from Animal, so I suggest you change it to
bool operator< (const Animal & lhs, const Animal & rhs)
{ return lhs.get_age() < rhs.get_age(); }
This has the benefit of treating both sides identically, rather than one being implicit.
template<typename T>
bool operator<(const T& one, const T& two)
{
return one.operator<(two);
}
This template matches all types and is entirely superfluous. a < b can call either a member or a free operator <. Just delete this template.
I have two questions.
First of all I have a little problem with the understanding of const pointers to const values. I don't get why B::insert works, while C::insert results in a compiler error. I mean doesn't the list in C exactly equals the parameter of C::insert?
My second question is whether A const * const a, could also be written as const A& a.
class A
{
//Do stuff
};
class B
{
private:
list<A const *> l;
public:
void insert(A const * const a)
{
l.push_back(a);
}
};
class C
{
private:
list<A const * const> l;
public:
void insert(A const * const a)
{
l.push_back(a);
}
};
Edit (Compile error):
g++ -Wall -c -O2 "sonnensystem.cpp" -std=c++11 (im Verzeichnis: C:\Users\Kenan\Desktop\OPR\cppcode\Konzepte\Kapselung\Architektur\sonnensystem01)
In file included from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/x86_64-w64-mingw32/bits/c++allocator.h:33:0,
from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/bits/allocator.h:46,
from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/string:41,
from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/bits/locale_classes.h:40,
from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/bits/ios_base.h:41,
from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/ios:42,
from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/ostream:38,
from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/iostream:39,
from sonnensystem.cpp:1:
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/ext/new_allocator.h: In instantiation of 'struct __gnu_cxx::new_allocator<const A* const>':
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/bits/allocator.h:92:11: required from 'class std::allocator<const A* const>'
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/bits/stl_list.h:315:9: required from 'class std::__cxx11::_List_base<const A* const, std::allocator<const A* const> >'
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/bits/stl_list.h:507:11: required from 'class std::__cxx11::list<const A* const>'
sonnensystem.cpp:28:27: required from here
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/ext/new_allocator.h:93:7: error: 'const _Tp* __gnu_cxx::new_allocator<_Tp>::address(__gnu_cxx::new_allocator<_Tp>::const_reference) const [with _Tp = const A* const; __gnu_cxx::new_allocator<_Tp>::const_pointer = const A* const*; __gnu_cxx::new_allocator<_Tp>::const_reference = const A* const&]' cannot be overloaded
address(const_reference __x) const _GLIBCXX_NOEXCEPT
^
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/ext/new_allocator.h:89:7: error: with '_Tp* __gnu_cxx::new_allocator<_Tp>::address(__gnu_cxx::new_allocator<_Tp>::reference) const [with _Tp = const A* const; __gnu_cxx::new_allocator<_Tp>::pointer = const A* const*; __gnu_cxx::new_allocator<_Tp>::reference = const A* const&]'
address(reference __x) const _GLIBCXX_NOEXCEPT
^
Kompilierung fehlgeschlagen.
In your declaration A const * const, the first const says that the A * pointer points to a value that can't be changed (a const pointer). The second const says that the value of that pointer can't be changed, just like a const int can't be changed. Since list (and other standard containers) require their members to be assignable, they can't be const values.
For your second question, a A const * const and const A& are similar, but not interchangeable, as the ways you use them are different.
When using std::list<T>, one of the requirements for T is that it is CopyAssignable. See http://en.cppreference.com/w/cpp/container/list.
When you use a const type as the parameter, that requirement is not met. You will see a similar error, if not the same error, if you use:
std::list<const int> a;
a.push_back(10);
Anyway,
list<A const * const> l;
is not usable.
The only real difference between A const * const and A const & is that it is easier to check that the pointer is invalid (you could cast a nul pointer to A and then dereference to get a null A reference, it's just easier to go if(!a)).
The C::insert case is due to the code trying to assign to the internal node value. It would probably work if you used emplace_back instead of push_back.
I am working on my own graph project in C++ at the moment and I have come along a problem which I'm sure it's easy to solve but I can't seem to get it right. I am building a template graph class with a vertex class declared inside of it as such:
template <typename T>
class graph{
public:
class vertex{
public:
bool visited; //used for paths. True if vertex has been visited
//vertex constructor
vertex(const T& d = T{}, int i = 0): data(d), visited(false), id(i){
std::cout << "Just created a vertex using its constructor :)\n";}
//vertex move constructor
vertex(T&& d, int i = 0): data(std::move(d)), visited(false), id(i){}
//returns vertex ID
int returnID() const{ return id; };
//returns data in vertex
T& operator*(){ return retrieve(); }
//returns const reference to data in vertex
const T& operator*() const{ return retrieve(); }
//returns list of adjacent vertices
std::list<vertex>& getList() const{ return adjacent; }
//adds vertex to current vertex's adjacency list
void addToList(const vertex& add){
if(!isAdjacent(add))
adjacent.push_back(add);
}
//returns true if vertices are adjacent
bool isAdjacent(const vertex& add){
return (find(begin(adjacent), end(adjacent), add) == adjacent.end());
}
//overloaded equal operator for vertex class
bool operator==(const vertex& add){
if(data == *add && id == add.returnID()) return true;
return false;
}
private:
T data; //vertex stores data of any type
std::list<vertex> adjacent; //list of adjacent vertices
int id;
T& retrieve() const{ return data; }
];
];
I keep getting this error:
g++ -std=c++11 -Wno-reorder -Wall -pedantic -o executable.x main.cpp
In file included from main.cpp:2:0:
graph.h: In instantiation of ‘T& graph<T>::vertex::retrieve() const [with T = int]’:
graph.h:70:47: required from ‘const T& graph<T>::vertex::operator*() const [with T = int]’
graph.h:84:17: required from ‘bool graph<T>::vertex::operator==(const graph<T>::vertex&) [with T = int]’
/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.4/include/g++-v4/bits/stl_algo.h:139:46: required from ‘_InputIterator std::__find(_InputIterator, _InputIterator, const _Tp&, std::input_iterator_tag) [with _InputIterator = std::_List_iterator<graph<int>::vertex>; _Tp = graph<int>::vertex]’
/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.4/include/g++-v4/bits/stl_algo.h:4441:45: required from ‘_IIter std::find(_IIter, _IIter, const _Tp&) [with _IIter = std::_List_iterator<graph<int>::vertex>; _Tp = graph<int>::vertex]’
graph.h:80:54: required from ‘bool graph<T>::vertex::isAdjacent(const graph<T>::vertex&) [with T = int]’
graph.h:75:24: required from ‘void graph<T>::vertex::addToList(const graph<T>::vertex&) [with T = int]’
graph.hpp:25:4: required from ‘bool graph<T>::addEdge(graph<T>::vertex&, graph<T>::vertex&) [with T = int]’
main.cpp:12:18: required from here
graph.h:92:31: error: invalid initialization of reference of type ‘int&’ from expression of type ‘const int’
T& retrieve() const{ return data; }
^
graph.h: In member function ‘T& graph<T>::vertex::retrieve() const [with T = int]’:
graph.h:92:37: warning: control reaches end of non-void function [-Wreturn-type]
T& retrieve() const{ return data; }
And to sum up the problem it seems to have an issue with my private T& retrieve() function. It keeps saying invalid initialization of type 'int&' from expression with type 'const int' referring to the data it is returning, which is private member data of type T (instantiated in main as an int). Any help would be greatly appreciated! Thanks
T data;
...
T& retrieve() const{ return data; }
The const modifier makes this method a const method. Which means that, essentially, its this is a pointer to a const class instance. Since data was not declared with a mutable modifier, data is a const value, and your compiler is complaining because it can't return a reference to a mutable value, because data is a constant value.
Either change the method to:
const T& retrieve() const{ return data; }
Or, I don't see why a reference here is needed, just:
T retrieve() const{ return data; }
P.S. You should try to make sense of these compiler errors, before giving up so quickly. It's true that C++ compilation errors are legendary for their typical obtuseness, but in this case you should be able to figure out what the compiler is telling you, after staring at those error messages, for a few minutes.
I have written a custom allocator that allocates memory in a shared memory segment.
This line of code compiles (and runs) fine:
shp_arr = new (vecmem) vector<shape *,smallocator <shape*> > ;
But this line of code:
shp_queue = new (queuemem) queue< shape *, deque < shape *, smallocator< shape * > > > ;
gives me a number of errors. Here they are:
/usr/local/lib/gcc/i686-pc-cygwin/4.7.3/../../../../include/c++/4.7.3/bits/stl_deque.h: In
instantiation of ‘std::_Deque_base<_Tp, _Alloc>::_Map_alloc_type std::_Deque_base<_Tp,
_Alloc>::_M_get_map_allocator() const [with _Tp = shape*; _Alloc = smallocator<shape*>;
std::_Deque_base<_Tp, _Alloc>::_Map_alloc_type = smallocator<shape**>]’:
/usr/local/lib/gcc/i686-pc-cygwin/4.7.3/../../../../include/c++/4.7.3/bits/stl_deque.h:549:9:
required from ‘void std::_Deque_base<_Tp, _Alloc>::_M_deallocate_map(_Tp**, std::size_t) [with _Tp =
shape*; _Alloc = smallocator<shape*>; std::size_t = unsigned int]’
/usr/local/lib/gcc/i686-pc-cygwin/4.7.3/../../../../include/c++/4.7.3/bits/stl_deque.h:568:4:
required from ‘std::_Deque_base<_Tp, _Alloc>::~_Deque_base() [with _Tp = shape*; _Alloc =
smallocator<shape*>]’
/usr/local/lib/gcc/i686-pc-cygwin/4.7.3/../../../../include/c++/4.7.3/bits/stl_deque.h:781:15:
required from ‘std::deque<_Tp, _Alloc>::deque() [with _Tp = shape*; _Alloc = smallocator<shape*>]’
file.cpp:233:30: required from here
/usr/local/lib/gcc/i686-pc-cygwin/4.7.3/../../../../include/c++/4.7.3/bits/stl_deque.h:529:53: error:
no matching function for call to ‘smallocator<shape**>::smallocator(const _Tp_alloc_type&)’
/usr/local/lib/gcc/i686-pc-cygwin/4.7.3/../../../../include/c++/4.7.3/bits/stl_deque.h:529:53: note:
candidates are:
In file included from file.cpp:20:0:
smallocator.hpp:41:3: note: smallocator<T>::smallocator(const smallocator<T>&) [with T = shape**;
smallocator<T> = smallocator<shape**>]
smallocator.hpp:41:3: note: no known conversion for argument 1 from ‘const _Tp_alloc_type {aka const
smallocator<shape*>}’ to ‘const smallocator<shape**>&’
smallocator.hpp:40:3: note: smallocator<T>::smallocator() [with T = shape**]
smallocator.hpp:40:3: note: candidate expects 0 arguments, 1 provided
The interface to smallocator looks like this:
template <typename T>
class smallocator: public std::allocator<T>
{
public:
typedef size_t size_type;
typedef T* pointer;
typedef const T* const_pointer;
template<typename _Tp1>
struct rebind
{
typedef smallocator<_Tp1> other;
};
pointer allocate(size_type n, const void *hint=0)
{
...
}
void deallocate(pointer p, size_type n)
{
...
}
smallocator() throw(): std::allocator<T>() { std::cout <<"Hello allocator" <<std::endl;}
smallocator(const smallocator &a) throw(): std::allocator<T>(a) { }
~smallocator() throw() { }
};
Does anyone know what the problem is? Thanks!
You did not provide the following constructor for your smallocator :
template <class U>
smallocator(const smallocator<U>& a) throw();
You need all three :
smallocator() throw();
smallocator(const smallocator& a) throw();
template <class U>
smallocator(const smallocator<U>& a) throw();
I have a std::set container whose elements are objects of the following class:
class LaneConnector {
public:
const Lane* getLaneFrom() const {
return From;
}
const Lane* getLaneTo() const {
return To;
}
private:
Lane* From;
Lane* To;
}
and my comparator function is as follows:
struct MyLaneConectorSorter {
bool operator() (LaneConnector * c, LaneConnector * d)
{
Lane* a = const_cast<Lane*>(c->getLaneFrom());
Lane* b = const_cast<Lane*>(d->getLaneFrom());
return (a->getLaneID() < b->getLaneID());
}
} myLaneConnectorSorter;
Now when I try to sort the elements in the set with:
//dont panic, the container just came through a const_iterator of a std::map :)
const std::set<LaneConnector*> & tempLC = (*it_cnn).second;
std::sort(tempLC.begin(), tempLC.end(), myLaneConnectorSorter);
I get a frenzy of errors starting with the following lines, Appreciate if you help me solve this problem.
Thanks:
/usr/include/c++/4.6/bits/stl_algo.h: In function ‘void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = std::_Rb_tree_const_iterator<LaneConnector*>, _Compare = {anonymous}::MyLaneConectorSorter]’:
/home/.../dev/Basic/shared/conf/simpleconf.cpp:1104:65: instantiated from here
/usr/include/c++/4.6/bits/stl_algo.h:5368:4: error: no match for ‘operator-’ in ‘__last - __first’
/usr/include/c++/4.6/bits/stl_algo.h:5368:4: note: candidates are:
/usr/include/c++/4.6/bits/stl_iterator.h:321:5: note: template<class _Iterator> typename std::reverse_iterator::difference_type std::operator-(const std::reverse_iterator<_Iterator>&, const std::reverse_iterator<_Iterator>&)
/usr/include/c++/4.6/bits/stl_iterator.h:378:5: note: template<class _IteratorL, class _IteratorR> typename std::reverse_iterator<_IteratorL>::difference_type std::operator-(const std::reverse_iterator<_IteratorL>&, const std::reverse_iterator<_IteratorR>&)
/usr/include/c++/4.6/bits/stl_bvector.h:181:3: note: std::ptrdiff_t std::operator-(const std::_Bit_iterator_base&, const std::_Bit_iterator_base&)
/usr/include/c++/4.6/bits/stl_bvector.h:181:3: note: no known conversion for argument 1 from ‘std::_Rb_tree_const_iterator<LaneConnector*>’ to ‘const std::_Bit_iterator_base&’
First, you cannot sort an std::set. It is a sorted structure, sorting happens upon construction or insertion.
Second, you can construct an std::set with your own sorting functor, and you can avoid unnecessary const_casts by making it take const pointers:
struct MyLaneConectorSorter {
bool operator() (const LaneConnector* lhs, const LaneConnector* rhs) const
{
// you may want to put some null pointer checks in here
const Lane* a = lhs->getLaneFrom();
const Lane* b = rhs->getLaneFrom();
return a->getLaneID() < b->getLaneID();
}
};
and instantiate the set like this:
std::set<LaneConnector*, MyLaneConectorSorter> s(MyLaneConectorSorter());
or, if you want to construct it from a different set, with a different ordering,
std::set<LaneConnector*> orig = ..... ;
....
std::set<LaneConnector*, MyLaneConectorSorter> s(orig.begin(), orig.end(), MyLaneConectorSorter());