Dijkstras algorithm with priority_queue - c++

I am trying to implement Dijkstra's algorithm. I am using this priority_queue
priority_queue<pair<PathInfo,string>,vector<pair<PathInfo,string> >,QueueComp> p;
where
class QueueComp{
PathComp* pc;
public:
QueueComp(PathComp*);
bool operator ()(const pair<PathInfo,string>&,const pair<PathInfo,string>& );
};
is my "Compare" function. The error is that QueueComp does not have a default constructor and I am not permitted to create one. What can I do to make my code compile? Btw this is the error
error: no matching function for call to 'QueueComp::QueueComp()'
This is the pathcomp.h
class PathComp{
public:
virtual bool betterThan(const PathInfo& path1,const PathInfo& path2)=0;
};
This is the pathcomppl.h
#include "pathcomp.h"
class PathCompPL:public PathComp{
public:
virtual bool betterThan(const PathInfo& path1,const PathInfo& path2);
};
This is the pathcomppl.cpp
#include "pathcomppl.h"
bool PathCompPL::betterThan(const PathInfo& path1,const PathInfo& path2){
if (path1.getTotalPrice()>path2.getTotalPrice())
return true;
if (path1.getTotalPrice()==path2.getTotalPrice() && path1.getTotalLength()>path2.getTotalLength())
return true;
return false;
}
Expanded error message
main.cpp: In constructor ‘std::priority_queue<_Tp, _Sequence, _Compare>::priority_queue(const _Compare&, const _Sequence&) [with _Tp = std::pair<PathInfo, std::basic_string<char> >; _Sequence = std::vector<std::pair<PathInfo, std::basic_string<char> > >; _Compare = QueueComp]’:
main.cpp:11:87: error: no matching function for call to ‘QueueComp::QueueComp()’
main.cpp:11:87: note: candidates are:
In file included from main.cpp:5:0:
queuecomp.h:14:5: note: QueueComp::QueueComp(PathComp*)
queuecomp.h:14:5: note: candidate expects 1 argument, 0 provided
queuecomp.h:10:7: note: QueueComp::QueueComp(const QueueComp&)
queuecomp.h:10:7: note: candidate expects 1 argument, 0 provided

You need to initialize your priority queue with additional parameter since you have non-default constructor.
priority_queue<pair<PathInfo,string>,vector<pair<PathInfo,string> >,QueueComp> p(QueueComp(ptrToPathCompObject));
The additional parameter (QueueComp(ptrToPathCompObject)) should fix your problem.
I am assuming that you have already implemented the operator() in QueueComp class.

You do not have a default constructor, because you are supposed to initialize the variable called pc. You have this constructor:
QueueComp(PathComp*);
You have to implement it so that pc is associated to the parameter.
As about your second question: The first element is your next priority, the second element is the set of lower priorities and the third is the queue comparison. I hope this helps you.

It looks like your issue is with implementing a proper comparator. One alternative you might consider is to create the comparator like the following
struct CompareEdgeWeights : public binary_function<PathInfo*, PathInfo*, bool>
{
bool operator()(const PathInfo* left, const PathInfo* right) const
{
return left->getEdgeWeight() > right->getEdgeWeight();
}
}; // end struct
// Priority queue of node edges
priority_queue<PathInfo*,vector<PathInfo*>,CompareEdgeWeights > * edgePriorityQueue;
Have this struct inherit from binary_function and overload the operator (). You can then use this as your comparator for keeping the edges sorted from lowest to highest weight value. Note: you may have to tweak this a bit to conform to your implementation. It is difficult to give a 100% correct suggestion without seeing more of your implementation.

Related

C++ error:[ invalid operands to binary expression ('std::map<int, std::function<void ()>, std::less<int>...]

With this following code:
#include <map>
#include <functional>
#include "main.h"
std::map<int,std::function<void()>> fnc_event_to;
void testFunction();
void initialize() {
fnc_event_to[1] = testFunction;
bool boolean = fnc_event_to[2] == testFunction;//<- error
pros::lcd::initialize();
pros::lcd::print(2,"%d",boolean);
}
I recieve this error:
invalid operands to binary expression ('std::map<int, std::function<void ()>, std::less<int>, std::allocator<std::pair<const int, std::function<void ()> > > >::mapped_type' (aka 'std::function<void ()>') and 'void (*)()')
How come I can assign the function pointer to the map but I am not able to compare it with a function pointer?
Also, if a key is not defined, what will the map return?
Is there a way to compare the std::function so I can see whether its a null function pointer or is it defined already?
Or is there a better solution for this? Originally, I'm using a while(1) loop to trap the thread and the map is just a map of what the program should do when a variable reaches the key(int). The variable is changed in a separate task so its multitasking. I couldn't use the .contains() method since I'm not using C++ 20 yet.
This is just posted for reference. Answers are quoted from #0x499602D2 and #LightnessRacesInOrbit.
Either use:
if (fnc_event_to[2]){
}
Or
if(fnc_event_to.find(2) != fnc_event_to.end()){
}
Be aware that the first option will create an empty element, so if you give the map the same value, it will already be created, and it will return true.
The standard class std::function has only these comparison operator ==
template<class R, class... ArgTypes>
bool operator==(const function<R(ArgTypes...)>&, nullptr_t) noexcept;
template<class R, class... ArgTypes>
bool operator==(nullptr_t, const function<R(ArgTypes...)>&) noexcept;
So you can only check whether an object of the class is "empty".

Returning a value from a map matching the type of the return value

I received the following error
In file included from /Users/james/ClionProjects/United States Computing Olympiad/graphs.cpp:2:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string:439:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/algorithm:628:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1673:31: error: no matching constructor for initialization of 'Vertex'
::new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...);
And here is an abridged version of the relevant portion of my code:
class Vertex {
public:
int label;
vector<Vertex> adjacent_vertices;
Vertex(const int l) : label(l) { }
Vertex(const int l, vector<Vertex> adjacents) : label(l), adjacent_vertices(adjacents) { }
Vertex(const Vertex& other_vertex) : label(other_vertex.label), adjacent_vertices(other_vertex.adjacent_vertices){ }
};
class Graph {
public:
unordered_map<int, Vertex> vertices;
protected:
Vertex getmake_vertex(const int v) {
if (vertices.find(v) == vertices.end() ) {
// not found, make new vertex
vertices[v] = Vertex(v);
}
return vertices[v];
};
};
I have confirmed that running this with everything else commented out produces a compiler error. Can someone explain to my why this occurs and how I can fix it? Here is a gist with the full compiler output.
When you say vertices[v] = Vertex(v); it has to create a Vertex for the key v (before the assignment), but Vertex has no default constructor.
What you should use is vertices.insert(make_pair(v, Vertex(v))) or even vertices.emplace(v, Vertex(v))
This also applies to return vertices[v];. Even though you and I know that there is always a value for v already by the time this return statement is hit, the compiler doesn't and still has to generate the code to potentially make one, and that is causing an error.
Setting it to return vertices.find(v)->second; will fix that part. No need to check and make sure the find value isn't end since we just put it in if it wasn't there.
Using operator[] requires the mapped_type (Vertex) in your case to be default constructible1, because it inserts a default-constructed1 mapped_type if key doesn't exist in the map. This is a run-time decision, so even if the key actually exists you still need the default constructor at compile-time.
In C++17, use try_emplace:
Vertex getmake_vertex(const int v) {
return vertices.try_emplace(v, v).first->second;
}
Otherwise, use insert or emplace.
Vertex getmake_vertex(const int v) {
return vertices.insert({v, v}).first->second;
}
(You may need to use Vertex(v) if you make the Vertex(int) constructor explicit, which you probably should.)
None of those actually inserts if the key is already in the map. All three
returns a pair<iterator, bool> with the iterator pointing to the element with the specified key.
1 Not quite true, but true enough for our purposes.
If I read this part of the error message(s) correct, it requires a default constructor for Vertex; especially this:
requires 2 arguments, but 0 were provided
/Users/james/ClionProjects/United States Computing Olympiad/graphs.cpp:14:5: note: candidate constructor not viable: requires single argument 'l', but no arguments were provided
Vertex(const int l) : label(l) { }
^
/Users/james/ClionProjects/United States Computing Olympiad/graphs.cpp:16:5: note: candidate constructor not viable: requires single argument 'other_vertex', but no arguments were provided
Vertex(const Vertex& other_vertex) : label(other_vertex.label), adjacent_vertices(other_vertex.adjacent_vertices){ }
^
/Users/james/ClionProjects/United States Computing Olympiad/graphs.cpp:15:5: note: candidate constructor not viable: requires 2 arguments, but 0 were provided
Vertex(const int l, vector<Vertex> adjacents) : label(l), adjacent_vertices(adjacents) { }

C++ BinarySearchTree Inserting an element

So I'm getting these errors when trying to insert to a binary search tree, I've literally been stuck on this one problem for hours not knowing what to do and I couldn't find anything on the internet to help so thanks in advance.
In file included from Indexer.h:19,
from Indexer.cpp:20:
BinarySearchTree.h: In member function ‘void BinarySearchTree<Comparable>::insert(const Comparable&, BinarySearchTree<Comparable>::BinaryNode*&) [with Comparable = Word]’:
BinarySearchTree.h:108: instantiated from ‘void BinarySearchTree<Comparable>::insert(const Comparable&) [with Comparable = Word]’
Indexer.cpp:109: instantiated from here
BinarySearchTree.h:165: error: passing ‘const Word’ as ‘this’ argument of ‘bool Word::operator<(Word&)’ discards qualifiers
BinarySearchTree.h:167: error: no match for ‘operator<’ in ‘t->BinarySearchTree<Word>::BinaryNode::element < x’
Word.h:33: note: candidates are: bool Word::operator<(Word&)
make: *** [Indexer.o] Error 1
And the Code I think is creating it is from Indexer.cpp line 109
Word takes in two parameters, current being the string and count is equal to 0 for this function.
Indexer.cpp
BinarySearchTree<Word> filterTree;
Line 109: filterTree.insert(Word(current, count));
BinarySearchTree.h
void insert( const Comparable & x )
{
Line:108 insert( x, root );
}
Word.cpp :operator<
bool Word::operator<(Word &RHS)
{
if(m_wordText < RHS.GetWord())
{
return true;
}
else
return false;
}
Member comparators should (almost) always be const functions that take const parameters,
bool Word::operator<(Word const&) const;
Any function called within a const function must also be const itself
std::string Word::GetWord() const;
(As #NeilKirk correctly points out this should probably return std::string const&).
You should learn about const correctness as it can stop you from making silly mistakes in your code.
Also using a non-member comparator is usually preferred as it allows both sides of the expression to use conversion operators
bool operator<(Word const& lhs, Word const& rhs)
{
return lhs.GetWord() < rhs.GetWord();
}

C++ Templates Error: no matching function for call

I get the error mentioned here:
C++ Templates Error: no matching function for call std::vector<int, std::allocator<int> >
Here is the error(again):
main.cpp: In function ‘int main()’:
main.cpp:21:21: error: no matching function for call to ‘Test<int>::foo(std::vector<int, std::allocator<int> >)’
main.cpp:21:21: note: candidate is:
main.cpp:14:6: note: void Test<T>::foo(std::vector<T>&) [with T = int]
main.cpp:14:6: note: no known conversion for argument 1 from ‘std::vector<int, std::allocator<int> >’ to ‘std::vector<int, std::allocator<int> >&’
The problem is that I have a more complex situation and I don't know how to solve it (without breaking too much code).
I have a Binary Search Tree class that is generic. I want to populate a vector of elements of type T(generic) with all the values from the binary search tree nodes - so I can't make the vector const. The function that traverses the tree is recursive.
So I have:
/*main*/
BST<int> t;
t.add(21);
t.add(12);
//.... etc.
vector<int> elements;
t.inorder(elements);
/* ------------ */
and:
/*BST.h*/
template<typename T>
class BST{
//....
Node<T>* root;
//....
void inorder_rec(Node<T>* root, vector<T>& result);
void inorder(vector<T>& result);
//....
};
template<typename T>
void BST<T>::inorder_rec(Node<T>* root, vector<T>& result){
// recursive call for the child nodes
}
void BST<T>::inorder(vector<T>& result){
inorder_rec(this->root, result);
}
/* ------------ */
You are trying to call a function that takes a reference with a temporary. A temporary can only bind to a reference to const. Also, it would be wise to show, where the error actually originated.
Is this your actual code? The definitions of inorder and inorder_rec need to have return types. Otherwise, this part of the code looks fine, no temporary in sight:
vector<int> elements;
t.inorder(elements);
Dumb question, but did you save your file? Or is this error coming from a different part of the code?

C++ stable_partition Compiler Error

I'm trying to extend an example I found in Koenig and Moo's "Accelerated C++." I've got the following code which attempts to split a vector into two partitions.
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
struct MyClass {
int* MyInt;
MyClass() : MyInt(NULL) {}
};
struct AnalyzeMemOps {
vector<MyClass> AllMyClassRecords; // Where I keep the MyClass instances
bool sameBaseReg(MyClass m);
vector<MyClass> splitBySameBase(vector<MyClass>& main);
AnalyzeMemOps() {}
};
// Predicate function for stable_partition
bool AnalyzeMemOps::sameBaseReg(MyClass m) {
return true;
}
vector<MyClass> AnalyzeMemOps::splitBySameBase(vector<MyClass>& main) {
vector<MyClass>::iterator it =
stable_partition(main.begin(), main.end(), sameBaseReg); // Error is here
vector<MyClass> sameBases(it, main.end());
main.erase(it, main.end());
// Print results
cout << "Split By Same Base: Returning SameBase Instrs\n";
for (vector<MyClass>::iterator i = sameBases.begin(); i != sameBases.end(); ++i) {
cout << " " << i->MyInt << "\n";
}
return sameBases;
}
int main() {
AnalyzeMemOps AMCR;
MyClass m;
AMCR.AllMyClassRecords.push_back(m);
AMCR.AllMyClassRecords.push_back(m);
AMCR.AllMyClassRecords.push_back(m);
vector<MyClass> t = AMCR.splitBySameBase(AMCR.AllMyClassRecords);
}
I get an error when I attempt to compile this file with g++:
Tile.cpp: In member function \u2018std::vector<MyClass, std::allocator<MyClass> > AnalyzeMemOps::splitBySameBase(std::vector<MyClass, std::allocator<MyClass> >&)\u2019:
Tile.cpp:26: error: no matching function for call to \u2018stable_partition(__gnu_cxx::__normal_iterator<MyClass*, std::vector<MyClass, std::allocator<MyClass> > >, __gnu_cxx::__normal_iterator<MyClass*, std::vector<MyClass, std::allocator<MyClass> > >, <unresolved overloaded function type>)\u2019
/usr/include/c++/4.4/bits/stl_algo.h:1864: note: candidates are: _BIter std::stable_partition(_BIter, _BIter, _Predicate) [with _BIter = __gnu_cxx::__normal_iterator<MyClass*, std::vector<MyClass, std::allocator<MyClass> > >, _Predicate = bool (AnalyzeMemOps::*)(MyClass)]
make: *** [a.out] Error 1
Obviously this is a toy example, but I've checked the function prototypes and I'm not sure where I'm going wrong here. Any suggestions?
The problem is that sameBaseReg is a member function of AnalyzeMemOps. You can't use it like an ordinary non-member function because it can only be called on an object.
If you have a modern compiler that supports C++0x, C++ TR1, or if you have Boost handy, you can use bind to bind the pointer to member function to the this object:
std::bind(&AnalyzeMemOps::sameBaseReg, this, std::placeholders::_1)
In the current C++ standard library, the <functional> library has std::mem_fun, std::bind1st, and other functions that can help with this, but they are an absolute beating to use effectively.
You'll need to use mem_fun to turn the member function into an function object, then use bind1st to supply the this pointer.
I was never particularly successful getting this stuff to work on a regular basis (the standard library algorithms seem to be mainly designed for use with freestanding functions or hand-written predicate classes), but something like this should do the trick:
vector<MyClass>::iterator it =
stable_partition(main.begin(),
main.end(),
bind1st(mem_fun(&AnalyzeMemOps::sameBaseReg),
this));
mem_fun gives you back a function object that takes two arguments, the first being the object to invoke mem_fun's member function on, and the second being the single argument to the member function.
bind1st takes a function object that takes two arguments, and returns you a new one that takes one argument, which when invoked via operator() will call the original function object with the bind1st's argument as its first argument and the supplied argument as the second.
The end result is that a new function object is created, that takes one argument, and that will call this->sameBaseReg, passing in the supplied argument.