Passing compare function for a generic class - c++

I want to create a priority queue for which I am using a heap(using array).The priority queue will be generic thus accept all data types as long as the client pass a compare function through constructor to compare the two types.
How can I create a constructor that will accept the compare function as a parameter? Moreover how can I make the compare function to be called when I check
return (Type a==Type b)
Eg.
struct node{
string val1;
string val2;
vector<node *> connectedNodes;
};
int compareNode(node a,node b){
//describe the compare
}
int main(){
PQueue<node> q(compareNode);
}
The PQueue class is implemented as an array. As the adding,bubbling-up, heapifying needs to compare two ValType I want them to compare using compareNode.

You don't have to do this: don't use an array, use the built-in priority-queue of the STL library in c++. It has its own compare function which you can alter.
Reference: http://www.cplusplus.com/reference/queue/priority_queue/
You can also see topcoder tutorials (for algorithmic usage).

Let me first give you a simple answer and then a more versatile one.
You can simply pass a function as parameter by declaring the type of that parameter to be the type of pointer function. You can also have variables of type pointer to function. For instance, if the declaration of your function is
int compareNode(node a, node b)
then you could do something like this:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
struct node{
string val1;
string val2;
vector<node *> connectedNodes;
};
int compareNode(node a,node b){
//describe the compare
return a.val2.compare(b.val2); // or any other code
}
template <class T>
class PQueue {
protected:
// this declares a protected member named compareFunction of type pointer to a function which takes 2 T parameters and returns a int. Note that all the parenthesis are mandatory
int (*compareFunction)(T, T);
public:
PQueue (int (*compareFunctionParameter)(T, T)) : compareFunction(compareFunctionParameter) {
// this constructor receives a pointer to function and initializes it's member to that pointer. If the constructor initialization list confuses you, you can read 'compareFunction = compareFunctionParameter '
}
int someMethod() {
// call the function through the pointer you have:
node n1, n2;
n1.val1 = "node1_val1";
n1.val2 = "zzz";
n2.val1 = "node2_val1";
n2.val2 = "aaa";
return compareFunction(n1, n2);
}
};
int main() {
PQueue<node> pq(compareNode);
cout << pq.someMethod() << endl;
return 0;
}
http://ideone.com/EPjbya
Hope this you can use this.
Now to the more versatile example.
C++11 introduces lambdas. http://www.cprogramming.com/c++11/c++11-lambda-closures.html http://www.stroustrup.com/C++11FAQ.html#lambda
#include <iostream>
#include <vector>
#include <string>
#include <functional>
using namespace std;
struct node{
string val1;
string val2;
vector<node *> connectedNodes;
};
int compareNode(node a,node b){
//describe the compare
return a.val2.compare(b.val2); // or any other code
}
template <class T, class Comparator>
class PQueue {
protected:
Comparator compareFunction;
public:
PQueue (Comparator compareFunctionParameter) : compareFunction(compareFunctionParameter) {
}
int someMethod() {
// call the function
node n1, n2;
n1.val1 = "node1_val1";
n1.val2 = "zzz";
n2.val1 = "node2_val1";
n2.val2 = "aaa";
return compareFunction(n1, n2);
}
};
int main() {
// queue with pointer to function
PQueue<node, int (*)(node, node)> pq(compareNode);
cout << pq.someMethod() << endl;
// queue with lamda (anonimous function)
PQueue<node, std::function<int (node, node)>> pq_lambda([](node a, node b) -> int {return a.val1.compare(b.val1);} );
cout << pq_lambda.someMethod() << endl;
return 0;
}
http://ideone.com/ryQmAn You need to compile this code for C++11 standard.
Here the template Comparator can be both pointer to function and lambda. If you are interested in lambdas, the two links I provided above should get you started.

Related

Can I emplace arguments into a class member without first default-constructing said member?

template <typename StoredT>
class InternalObject {
public:
using RefCountT = unsigned short;
template <typename... CtorTs>
static void* emplace(CtorTs&&...);
Types type;
RefCountT reference_count;
bool is_immovable;
StoredT stored_value;
InternalObject();
InternalObject(StoredT);
~InternalObject();
};
My class has a member StoredT stored_value which I would like to be able to construct using emplace and return a void* to it.
However, if I want to do this, I would have to do InternalObject<StoredT> *io_ptr = new InternalObject<StoredT>; which would force me to default-construct stored_value.
The solution I attempted was to allocate the appropriate amount of space as an array of unsigned char (the returned pointer is a heap pointer). Then, I tried to increment the pointer by appropriate amounts and modify the value there.
A more reproducible & complete example which does not produce a valid (non-POD) value for two.
#include <iostream>
#include <vector>
struct S {
int one;
std::vector<int> two;
};
int main() {
unsigned char *s_ptr = new unsigned char[sizeof(S)];
S *s = reinterpret_cast<S*>(s_ptr);
*s_ptr = 100; // Fine
std::vector<int> *vec_ptr = reinterpret_cast<std::vector<int>*>(s_ptr + sizeof(int));
*vec_ptr = {5,6,7};
std::cout << s->two.capacity() << "\n"; // big ol' number
return 0;
}
Consider using std::optional<StoredT>, which will allow you to defer the construction of the StoredT that you want to hold:
#include <optional>
template <typename StoredT>
class InternalObject {
public:
using RefCountT = unsigned short;
template <typename... CtorTs>
void emplace(CtorTs&&... args) {
stored_value.emplace(args...);
}
Types type;
RefCountT reference_count;
bool is_immovable;
std::optional<StoredT> stored_value;
InternalObject();
InternalObject(StoredT);
~InternalObject();
};

Passing function to template object when initializing template in C++

I'm trying to write an implementation for hash map, I'm not allowed to use anything from stdlib except for iostream, string and cassert.
It needs to be generic, so the values that populate the buckets can be of any type. I need templates for this, but can't manage to pass the hash function in any way. This would be the header file:
template<typename Value, typename hashFunction>
class hashTable{
public:
hashTable(int size){
//Creates an empty vector of size on the table
}
define(Value v){
loads value in Vector[hashFunction(v)];
}
...
private:
Vector with all the elements
}
Note: I guess I don't need templates for the keys, do I?
I can't define the hash function inside my class because I'd have to make one that works with all types (string to int, int to int, double to int, etc). So I guess the only solution is to pass the function as argument in my main. This would be the main.
int hashF(int v){return v}
int main(){
hashTable<int,int,hashF> table(5);
}
But this doesn't work, g++ tells me "expected type but got hashF". I guess I could pass a pointer to a function, but that seems like a hack rather than a real solution. Is there a better way?
template<typename Value, int(*fun)(Value)>
class hashTable {
std::vector<Value> v;
public:
hashTable(std::size_t size) : v(size) { }
void define(Value &&val) { v[fun(val)] = val; }
};
Live Demo
Non function pointer way:
template<typename Value, typename F>
class hashTable {
std::vector<Value> v;
F fun;
public:
hashTable(std::size_t size, F fun_) : v(size), fun(fun_) { }
void define(Value &&val) { v[fun(val)] = val; }
};
Live Demo
Managed to get it working with Neil's advice. My hash.h:
template<typename C, typename D, typename H>
class Tabla {
public:
Tabla(int s){
cout << hashF(3) << endl;
size=s;
}
private:
H hashF;
int size;
};
My hash.cpp
struct KeyHash {
unsigned long operator()(const int& k) const
{
return k % 10;
}
};
int main(){
Tabla<int,int,KeyHash> tab(3);
return 0;
}
This example is just to show I'm able to use the function inside the template, then I'd have to code the define and delete functions that use that KeyHash.
Dunno why I have to wrap it like this, but it works. Found the specifics of it here

Priority queue in Dijkstra's algorithm

This is my code for Dijkstra's algorithm:
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#define pp pair<int,int>
using namespace std;
struct pri
{
int operator() (const pair<int,int>&p1,const pair<int,int>&p2)
{
return p1.second<p2.second;
}
}p;
int main()
{
priority_queue<pp,vector<pp>,pri> q;
int n;
cin>>n;
vector<pp> g[n+1];
int e,u,v,w,i;
cin>>e;
for(i=0;i<e;i++)
{
cin>>u>>v>>w;
g[u].push_back(pp(v,w));
g[v].push_back(pp(u,w));
}
int s;
cin>>s;
int d[n+1];
for(i=1;i<=n;i++)
d[i]=999;
d[s]=0;
q.push(pp(s,d[s]));
while(!q.empty())
{
u=q.top().first;
q.pop();
int size=g[u].size();
for(int i=0;i<size;i++)
{
v=g[u][i].first;
w=g[u][i].second;
cout<<u<<" "<<" "<<w<<endl;
if(d[v]>d[u]+w)
{
d[v]=d[u]+w;
q.push(pp(v,d[v]));
}
}
}
for(i=1;i<=n;i++)
printf("node %d,min weight=%d\n",i,d[i]);
return 0;
}
In this I can't understand the working of
priority_queue<pp,vector<pp>,pri> q;
That is related to:
struct pri
{
int operator() (const pair<int,int>&p1,const pair<int,int>&p2)
{
return p1.second<p2.second;
}
}p;
What is the use of () operator in this? I mean how it functions in this code?
Also why are we using & in operator()?
Also, how does this comparator work in priority queue definition?
And why are we using constant in operator definition?
i mean to say how is exactly this comparison in operator working and cant we use any
other symbol as = * # or any other instead of ()
I think the compare function you write is wrong.
int operator() (const pair<int,int>&p1,const pair<int,int>&p2)
{
return p1.second<p2.second;
}
which the correct one should be
int operator() (const pair<int,int>&p1,const pair<int,int>&p2)
{
return p1.second>p2.second;
}
Because in priority_quequeyou can find that The expression comp(a,b), where comp is an object of this type and a and b are elements in the container, shall return true if a is considered to go before b in the strict weak ordering the function defines.
Because in the Dijkstra algorithm, the node with smaller value should has higher priority, thus the operator we used here should be
p1.second>p2.second
(By using your code to solve a problem, it took me a long time to figure out this problem that my program's results were always different with the correct one.)
(By the way, in the Dijkstra algorithm itself, I think once a node was pop as the smallest one, there is no need to pop it again and update all the nodes that connected to it. This could save a lot of time.)
struct pri {
int operator() (const pair<int,int>&p1,const pair<int,int>&p2)
{
return p1.second<p2.second;
}
}p;
Creates a function object by overloading () operator
This is passed to the priority_queue as the compare class
& is used to pass the pair as constant reference, making sure that no copying of actual arguments take place, (by passing them as reference), at same time the function can't modify their values (by using const keyword)
With the use of this function object, the queue determines how to insert the values (pair).
In this case the second value of pair is used for comparison.
When declaring variables (including function arguments), the & is to mark the variable as a reference. It's very basic and common thing to use references for some types of arguments, partly because it passes the arguments without creating copies (so good for e.g. a std::vector) and it also allows non-const references to be changed in the function as a form of output argument.
As for the use of operator() in a structure like this, it makes instances of the structure function objects, in other words, objects that can be invoked like a function.
I think your question is about the line priority_queue<pp,vector<pp>,pri> q;?
This declares a variable q of type priority_queue<pp,vector<pp>,pri>. priority_queue is defined as
template<class T,
class Container = vector<T>,
class Compare = less<typename Container::value_type> >
class priority_queue;
So, pp is the type of the elements, vector<pp> is the container (the same as the default), and pri is a function object which is used to compare items in the queue (Compare). The priority_queue uses Compare to order its elements. If the elements cannot be compared directly, or the default is not appropriate, then you can supply your own. In this case, the elements will be order by second member in each element pair.
Basically the same as the other answers, just a little more detail -- the operator() code is what defines how the priority queue should do comparisons to determine item priority in the queue. Using this type of framework, you can have a priority queue defined to store any type of objects, and the priority queue can be ordered according to any kind of custom ordering you want on the objects.
I refactored this code and checked it with hackerrank.
#include <cstdio>
#include <vector>
#include <queue>
#include <iostream>
#include <vector>
#include <deque>
#include <set>
#include <limits>
#include <iterator>
#include <algorithm>
#include <functional>
using namespace std;
struct pri
{
typedef pair<int,int> pp;
typedef deque<pri::pp > list;
typedef vector< pri::list > graph;
int operator() (pp&p1,const pp&p2)
{
return p1.second>p2.second;
}
typedef priority_queue< pri::pp, pri::list, pri > queue;
};
static int f1(const int x){ return x==std::numeric_limits<int>().max()?-1:x; }
int main()
{
int t;
cin>>t;
while(t--){
int n,e;
cin>>n>>e;
pri::graph g(n+1);
for(int i(0);i<e;i++){
int u,v,w;
cin>>u>>v>>w;
g[u].push_back(pri::pp(v,w));
g[v].push_back(pri::pp(u,w));
}
vector<int> d(n+1,std::numeric_limits<int>().max());
int s; cin>>s;
d[s]=0;
pri::queue q;
q.push(pri::pp(s,d[s]));
set<int> vs;
while(!q.empty()) {
const int u(q.top().first);
const pri::list& gu(g[u]);
q.pop();
vs.insert(u);
for( pri::list::const_iterator i(gu.begin()); i != gu.end(); ++i ) {
const int v(i->first), w(i->second);
if( vs.find(v)==vs.end() ){
// cout<<u<<" "<<v<<" "<<w<<endl;
if( d[v]>d[u]+w ) {
d[v]=d[u]+w;
q.push(pri::pp(v,d[v]));
}
}
}
}
copy_if(d.begin()+1,d.end(),d.begin(),std::bind2nd(std::not_equal_to<int>(),0));
transform(d.begin(),d.end()-2,ostream_iterator<int>(cout," "),f1);
cout<<endl;
}
return 0;
}

C++ Generic code for deleting pointer value in Map and vector of pointers

I have some generic code for deleting pointers within a vector or a value of a Map.
Is there a better way of doing this (without using shared_ptrs or any o fthe tr1 extensions )?
Also is the code correct?
Here is my code:
I have a namespace
#ifndef CONTAINERDELETE_H
#define CONTAINERDELETE_H
#include <functional>
#include <map>
#include <vector>
#include <algorithm>
namspace ContainerDelete{
template<class A, class B>
struct DeleteMap
{
bool operator()( pair<A,B> &x) const
{
delete x.second;
return true;
}
};
template<class T>
struct DeleteVector
{
bool operator()(T &x) const
{
delete x;
return true;
}
};
}
#endif
I would then use this namespace in some bit of code to delete a map or vector.
Test Map deletion.
#include "ContainerDelete.h"
using namespace std;
// Test function.
void TestMapDeletion()
{
// Add 10 string to map.
map<int,B*> testMap;
for( int Idx = 0; Idx < 10; ++Idx )
{
testMap[Idx] = new B();
}
// Now delete the map in a single line.
for_each( testMap.begin(),
testMap.end(),
ContainerDelete::DeleteMap<int,B*>());
}
Test Vector Deletion
// Test Function.
void TestVectorDeletion()
{
// Add 10 string to vector.
vector<B*> testVector;
for( int Index = 0; Index < 10; ++Index )
{
testVector.push_back( new B());
}
// Now delete the vector in a single line.
for_each( testVector.begin(),
testVector.end(),
ContainerDelete::DeleteVector<B*>());
}
Thanks,
Mike
Better would be if reduce the genericity as:
struct DeleteVector
{
template<class T> //use the template here!
void operator()(T &x) const
{
delete x;
}
};
if you do so, then you could simply write this:
for_each(testVector.begin(),
testVector.end(),
ContainerDelete::DeleteVector());
No need to pass type argument when you use DeleteVector, for it is not a class template anymore!
Similarly, you can implement DeleteMap functor.
You should also rename DeleteVector to DeleteT, and DeleteMap to DeletePairSecond, as both of these can be used more generically. For example, DeleteT can be used even with std::list, or even with arrays.
The code is ok. I can't imagine any other ways to delete the pointers. All you can do is to reduce explicit type specification like in upper question. I know one more uglier way to do it: functions deduce types of their template parameters. So you can write template function with the first argument - vector, second - ptr and then use std::bind of vector parameter to make this function accepting one parameter - ptr.
But functor is better and more flexible.

Can a functor retain values when passed to std::for_each?

According to the first answer to this question, the functor below should be able to retain a value after being passed to foreach ( I couldn't get the struct Accumulator in the example to compile, so built a class).
class Accumulator
{
public:
Accumulator(): counter(0){}
int counter;
void operator()(const Card & c) { counter += i; }
};
Example usage ( as per the example )
// Using a functor
Accumulator acc;
std::for_each(_cards.begin(), _cards.end(), acc);
// according to the example - acc.counter contains the sum of all
// elements of the deque
std::cout << acc.counter << std::endl;
_cards is implemented as a std::deque<Card>. No matter how long _cards gets, acc.counter is zero after the for_each completes. As I step through in the debugger I can see counter incrementing, however, so is it something to do with acc being passed by value?
This was just asked here.
The reason is that (as you guessed) std::for_each copies its functor, and calls on it. However, it also returns it, so as outlined in the answer linked to above, use the return value for for_each.
That said, you just need to use std::accumulate:
int counter = std::accumulate(_cards.begin(), _cards.end(), 0);
A functor and for_each isn't correct here.
For your usage (counting some, ignoring others), you'll probably need to supply your own functor and use count_if:
// unary_function lives in <functional>
struct is_face_up : std::unary_function<const Card&, const bool>
{
const bool operator()(const card& pC) const
{
return pC.isFaceUp(); // obviously I'm guessing
}
};
int faceUp = std::count_if(_cards.begin(), _cards.end(), is_face_up());
int faceDown = 52 - faceUp;
And with C++0x lambda's for fun (just because):
int faceUp = std::count_if(_cards.begin(), _cards.end(),
[](const Card& pC){ return pC.isFaceUp(); });
Much nicer.
Yes, it's definitely linked to acc being passed by value.
Modify your accumulator as follows :
class Accumulator
{
public:
Accumulator(): counter(new int(0)){}
boost::shared_ptr<int> counter;
void operator()(int i) { *counter += i; }
int value() { return *counter; }
};
This is because internally the std::for_each() makes a copy of the functor (as it is poassable to pass temporary object). So internally it does do the sum on the copy not on the object you provided.
The good news is that std::for_each() returns a copy of the functor as a result so you can access it from there.
Note: There are other standard algorithms you could use. Like std::accumulate().
But suppose this is just a simplified example and you need for_each() to something slightly tricker than the example there are a couple of techniques to allow you access to the accumulator object.
#include <iostream>
#include <algorithm>
#include <vector>
class Card{ public: int i;};
class Accumulator
{
public:
Accumulator(): counter(0){}
int counter;
void operator()(const Card & c) { counter += c.i; }
};
int main()
{
std::vector<Card> cards;
Accumulator a = std::for_each(cards.begin(), cards.end(), Accumulator());
std::cout << a.counter << std::endl;
}
Alternatively you can change you Accumalator to increment a reference that is used within the current scope.
#include <iostream>
#include <algorithm>
#include <vector>
class Card{ public: int i;};
class Accumulator
{
int& counter;
public:
// Pass a reference to constructor.
// Copy construction will pass this correctly into the internal object used by for_each
Accumulator(int& counterRef): counter(counterRef){}
void operator()(const Card & c) { counter += c.i; }
};
int main()
{
std::vector<Card> cards;
int counter = 0; // Count stored here.
std::for_each(cards.begin(), cards.end(), Accumulator(counter));
std::cout << counter << std::endl;
}