how to initialise this templated pair in c++? - c++

template<class V, class E>
class G
{
public:
G();
void InsertVertex(const V&);
void InsertEdge(const V&, const V&, const E& );
private:
typedef set<V,less<V> > vSet;
typedef pair<const V,V> ePair;
typedef multimap<V,V,less<V> > eSet;
typedef map<ePair,E, less<ePair> > edgeValueMap;
vSet vertices;
eSet edges;
edgeValueMap edgeVals;
};
template<class V,class E>
G<V,E>::G(){}
template<class V,class E>
void G<V,E>::InsertVertex(const V& a)
{
vertices.insert(a);
}
template<class V,class E>
void G<V,E>::InsertEdge(const V& a,const V& b, const E& val)
{
//create a pair
ePair<const V,v> e(a,b);
edges.insert(e);
edgeVals.insert(e,val);
}
int main()
{
G<char,int> g;
g.InsertVertex('a');
g.InsertVertex('b');
g.InsertVertex('c');
g.InsertEdge('a','b',1);
return 0;
}
while i create a pair using "ePair e(a,b)" i am getting error:
"template2.cpp:39:2: error: ‘G::ePair’ is not a template"
I am not sure exactly why this compile error is coming? am i missing anything here?

I was using make_pair to build actual map entries, it works here. But note that also the call edgeVals.insert(e,val); give error: so i modified that also:
template<class V,class E>
void G<V,E>::InsertEdge(const V& a,const V& b, const E& val)
{
//create a pair
ePair e = make_pair(a,b);
edges.insert(e);
edgeVals[e] = val;
}

Related

C++: Templated code compiles and runs fine with clang++, but fails with g++

Take a look at this implementation of a linked list:
#include <memory>
#include <type_traits>
#include <iostream>
using namespace std;
template<typename D>
class List {
struct Node {
shared_ptr<D> data;
Node* next;
Node(shared_ptr<D> d, Node* p, Node* n) : data(d), next(n) {}
~Node() {
data.reset();
delete next;
}
};
template <bool isconst = false>
struct iterator : public std::iterator<std::forward_iterator_tag, shared_ptr<D>> {
typedef std::forward_iterator_tag iterator_category;
typedef shared_ptr<D> value_type;
typedef std::ptrdiff_t Distance;
typedef typename conditional<isconst, const value_type&, value_type&>::type
Reference;
typedef typename conditional<isconst, const value_type*, value_type*>::type
Pointer;
typedef typename conditional<isconst, const Node*, Node*>::type
nodeptr;
iterator(nodeptr x = nullptr) : curr_node(x) {}
iterator(const iterator<false>& i) : curr_node(i.curr_node) {}
Reference operator*() const { return curr_node->data; }
Pointer operator->() const { return &(curr_node->data); }
template<bool A>
friend bool operator==(const iterator<A>& a, const iterator<A>& b) {
return a.curr_node == b.curr_node;
}
template<bool A>
friend bool operator!=(const iterator<A>& a, const iterator<A>& b) {
return !(a.curr_node == b.curr_node);
}
friend class List<D>;
iterator& operator++() {
curr_node = curr_node->next;
return *this;
}
private:
nodeptr curr_node;
};
public:
List() {
head = nullptr;
}
int len() const {
int ret = 0;
for (const auto& n : *this) {
ret++;
}
return ret;
}
~List() {
delete head;
}
std::ostream& dump(std::ostream &strm) const {
for (const auto s : *this) {
strm << *s << std::endl;
}
return strm;
}
iterator<false> begin() {
return iterator<false>(head);
}
iterator<false> end() {
return iterator<false>(nullptr);
}
iterator<true> begin() const {
return iterator<true>(head);
}
iterator<true> end() const {
return iterator<true>(nullptr);
}
private:
Node* head;
};
The part giving me problems is the iterator implementation for this list. The iterator template is supposed to provide both mutable and const iterators.
This is a program which uses this implementation:
#include "List.h"
#include <iostream>
int main( int argc, const char *argv[] ) {
List<int> l;
std::cout << l.len() << std::endl;
return 0;
}
The program compiles and runs fine if I use clang++, but the compilation fails for g++ with the following error:
In file included from t.cpp:1:
List.h: In instantiation of ‘struct List<int>::iterator<false>’:
List.h:136:5: required from ‘int List<D>::len() const [with D = int]’
t.cpp:7:24: required from here
List.h:64:21: error: redefinition of ‘template<bool A> bool operator==(const List<int>::iterator<isconst>&, const List<int>::iterator<isconst>&)’
friend bool operator==(const iterator<A>& a, const iterator<A>& b) {
^~~~~~~~
List.h:64:21: note: ‘template<bool A> bool operator==(const List<int>::iterator<isconst>&, const List<int>::iterator<isconst>&)’ previously declared here
List.h:69:21: error: redefinition of ‘template<bool A> bool operator!=(const List<int>::iterator<isconst>&, const List<int>::iterator<isconst>&)’
friend bool operator!=(const iterator<A>& a, const iterator<A>& b) {
^~~~~~~~
List.h:69:21: note: ‘template<bool A> bool operator!=(const List<int>::iterator<isconst>&, const List<int>::iterator<isconst>&)’ previously declared here
What's the cause of this error? How can I fix this?
The problem seems to be here:
template <bool isconst = false>
struct iterator : public std::iterator<std::forward_iterator_tag, shared_ptr<D>> {
template<bool A>
friend bool operator==(const iterator<A>& a, const iterator<A>& b) {
return a.curr_node == b.curr_node;
}
This is saying: For all values of isconst (the outer template parameter), define a template function template<bool A> bool operator==.
So instantiating iterator<true> will define template<bool A> bool operator==, and then instantiating iterator<false> will define template<bool A> bool operator== again, causing a redefinition error.
Solution: Remove the inner template. Have each instantiation of iterator only define its own operator==:
template <bool isconst = false>
struct iterator : public std::iterator<std::forward_iterator_tag, shared_ptr<D>> {
friend bool operator==(const iterator& a, const iterator& b) {
return a.curr_node == b.curr_node;
}
(Here iterator automatically refers to iterator<isconst>, i.e. the current instantiation.)

lazy evaluation implementation will not compile

The following code has a promise class, which takes a class, function from this class and an input, and which it evaluates into a result var when asked to do so. There is a vector class which can be initialized with a promise and a promise test class which for the purpose of this question just realizes the promise to resize a vector variable.
In the main I create two promise test variables: one for vector int and the other for vector double. The problem is that the code will not compile as given below (with g++ SUSE Linux 4.3.4 revision 152973) but compiles and runs fine if I remove t1 and v1. The compilation error I get says that the compiler cannot see the template promise constructor for the vector double variable.
Any ideas what might be happening? Its like the first instantiation of the test/vector pair shadows the second.
#include <iostream>
#include <vector>
using namespace std;
#define FUNC(O, I, R, F) void(O::*F)(const I&, R&) const
template<typename O, typename I, typename R, FUNC(O, I, R, F)>
struct promise
{
promise(const O& _o, const I& _x) : o(_o), x(_x)
{ }
inline void eval_into(R& r) const
{
(o.*(F))(x, r);
}
const O& o;
const I& x;
};
template<typename T>
struct vec: public vector<T>
{
typedef vector<T> base;
vec(const vec& v) : base(v)
{ }
vec() : base()
{ }
template<typename O, typename I, FUNC(O, I, vec, F)>
vec(const promise<O, I, vec, F>& p)
{
p.eval_into(*this);
}
};
template<typename T>
struct promise_test
{
typedef vec<T> vect;
inline void eval_f(const int& s, vect& r) const
{
r.resize(s);
}
typedef promise<promise_test, int, vect, &promise_test::eval_f> promise_type;
inline promise_type f(const int& s) const
{
return promise_type(*this, s);
}
};
int main(int argc, char** argv)
{
int x = 5;
promise_test<int> t1;
vec<int> v1(t1.f(x));
promise_test<double> t2;
vec<double> v2(t2.f(x));
cout << v2.size() << endl;
return 0;
}

Template class with get function ALWAYS returning reference,

How is it possible to have a templated class here called
FrontBackBuffer with template parameter TBackBufferType, TFrontBufferType
template< typename TBufferTypeFront, typename TBufferTypeBack = TBufferTypeFront>
class FrontBackBuffer{
public:
explicit FrontBackBuffer(
TBufferTypeFront const & m_front,
TBufferTypeBack const & m_back):
m_Front(m_front),
m_Back(m_back)
{
};
~FrontBackBuffer()
{};
typename std::remove_reference<
typename std::remove_pointer<TBufferTypeFront>::type
>::type & getFront(){return m_Front;} // error: invalid initialization of reference of type 'A&' from expression of type 'A*'| (here T is A)
typename std::remove_reference<
typename std::remove_pointer<TBufferTypeBack>::type
>::type & getBack(){return m_Back;}
TBufferTypeFront m_Front; ///< The front buffer
TBufferTypeBack m_Back; ///< The back buffer
};
I would like to achieve the following:
to be consistent in the code, I would prefere, to no matter what the Type inside the buffer is, to have a function getFront/Back which should always return a Reference to the buffer (either a const or a non-const depending on the type: e.g const int = T should return a const int & reference! I would like to write code like this
FrontBuffer<const int&, std::vector<int> > a;
a.getFront() = 4 //COmpile error! OK!;
a.getBack()[0] = 4;
FrontBuffer< int*, GAGAType * > b;
b.getBack() = GAGAType();
b.getFront() = int(4); // this is no ERROR, i would like to get the reference of the memory location pointet by int* ....
I would like this because I want to avoid changing the syntax if I change the buffer type from reference to pointer (where I need to dereference)
Is such a Buffer class possible to accept with all possible types (like shared_ptr)
asd
All I want is some access and it should be very performant, no copies and so on
I dont know really how to write this generic buffer? Somebody has any clue?
Thanks!!!
EDIT1 I want also to be able to assign to the dereferenced pointer:
b.getFront() = int(4); // this is no ERROR, i would like to get the reference of the memory location pointet by int* ....
Thats where my problem with traits comes in!
You need to specialize (traits technique) part of your template, like this:
template <typename T>
struct MyRefTypes {
typedef const T & Con;
typedef T& Ref;
typedef const T& CRef;
static Ref getRef(T& v) {
return v;
}
};
Update
Note the special function for returning reference - it is needed if you want to behave differently for pointers - returns references for it.
End Update
And make specialization for references and const references:
template <typename T>
struct MyRefTypes {
typedef const T & Con;
typedef T& Ref;
typedef const T& CRef;
static Ref getRef(T& v) {
return v;
}
};
//Specialization for Reference
template <typename T>
struct MyRefTypes<T&> {
typedef T & Con;
typedef T& Ref;
typedef const T& CRef;
static inline Ref getRef(T& v) {
return v;
}
};
//Specialization for const Reference
template <typename T>
struct MyRefTypes<const T&> {
typedef const T & Con;
typedef const T& Ref;
typedef const T& CRef;
static inline Ref getRef(const T& v) {
return v;
}
};
//Specialization for const
template <typename T>
struct MyRefTypes<const T> {
typedef const T & Con;
typedef const T& Ref;
typedef const T& CRef;
static inline Ref getRef(const T& v) {
return v;
}
};
Update
And this "special" specialization for pointers - so they will work as references:
//Specialization for pointers
template <typename T>
struct MyRefTypes<T*> {
typedef T* Con;
typedef T& Ref;
typedef T* const CRef; //! note this is a pointer....
static inline Ref getRef(T* v) {
return *v;
}
};
//Specialization for const pointers
template <typename T>
struct MyRefTypes<const T*> {
typedef const T* Con;
typedef const T& Ref;
typedef const T* const CRef; //! note this is a pointer....
static inline Ref getRef(const T* v) {
return *v;
}
};
((However I am not sure this specialization for pointers is a good design... ))
End Update
And usage inside your class template:
template< typename TBufferTypeFront, typename TBufferTypeBack = TBufferTypeFront>
class FrontBackBuffer{
public:
typedef typename MyRefTypes<TBufferTypeFront>::Ref TBufferTypeFrontRef;
typedef typename MyRefTypes<TBufferTypeFront>::CRef TBufferTypeFrontCRef;
typedef typename MyRefTypes<TBufferTypeFront>::Con TBufferTypeFrontCon;
typedef typename MyRefTypes<TBufferTypeBack >::Ref TBufferTypeBackRef;
typedef typename MyRefTypes<TBufferTypeBack >::CRef TBufferTypeBackCRef;
typedef typename MyRefTypes<TBufferTypeBack >::Con TBufferTypeBackCon;
explicit FrontBackBuffer(
TBufferTypeFrontCon m_front,
TBufferTypeBackCon m_back):
m_Front(m_front),
m_Back(m_back)
{
};
~FrontBackBuffer()
{};
// See here special functions from traits are used:
TBufferTypeFrontRef getFront(){return MyRefTypes<TBufferTypeFront>::getRef(m_Front); }
TBufferTypeBackRef getBack(){return MyRefTypes<TBufferTypeBack>::getRef(m_Back); }
TBufferTypeFront m_Front; ///< The front buffer
TBufferTypeBack m_Back; ///< The back buffer
};
It works as expected:
http://ideone.com/e7xfoN

unable to match function definition to an existing declaration

While attempting to provide an implimentation to this question, I got stuck on an error. I'm getting errors for 8 of my functions like this:
f:\code\utilities\hypergraph\hypergraph\hypergraph.h(233): error C2244: 'hypergraph::add_edge' : unable to match function definition to an existing declaration
f:\code\utilities\hypergraph\hypergraph\hypergraph.h(68) : see declaration of 'hypergraph::add_edge'
definition
'hypergraph::node_iter hypergraph::add_edge(void)'
existing declarations
'std::set::node*,ptr_cmp::node,P>,A>::const_iterator hypergraph::add_edge(void)'
for this class:
template<class T, class P>
struct ptr_cmp
: public std::binary_function<T, T, bool> {
P p_;
ptr_cmp(P p=P()) :p_(p) {}
bool operator()(const T* l, const T* r) const
{ return p_(*l, *r);}
};
template<class T, class P = std::less<T>, class A=std::allocator<T> >
class hypergraph {
typedef A sub_allocator;
public:
class node;
class edge;
typedef std::set<edge*, ptr_cmp<edge, std::less<edge> >, sub_allocator> edgeset;
typedef std::set<node*, ptr_cmp<node, P>, sub_allocator> nodeset;
typedef typename std::set<edge*, ptr_cmp<edge, std::less<edge> >, sub_allocator>::const_iterator edgeiter;
typedef typename std::set<node*, ptr_cmp<node, P>, sub_allocator>::const_iterator nodeiter;
class node { /*SNIP*/};
class edge { /*SNIP*/};
hypergraph(P pred=P(), A alloc=A());
nodeiter add_node(); /* beginning of 8 with the error */
nodeiter add_node(const T& rhs);
nodeiter add_node(T&& rhs);
nodeiter add_edge();
nodeiter erase(nodeiter iter);
nodeiter erase(node* iter);
nodeiter erase(edgeiter iter);
nodeiter erase(edge* iter); /* end of 8 with the error */
const nodeset& nodes() const;
const edgeset& edges() const;
A get_allocator() const;
protected:
hypergraph(const hypergraph& rhs);
hypergraph& operator=(const hypergraph& rhs);
A a_;
nodeset nodes_;
edgeset edges_;
unsigned int edgecount_;
};
And this function definition:
template<class T, class P, class A>
typename hypergraph<T,P,A>::node_iter hypergraph<T,P,A>::add_edge()
{
std::unique_ptr<edge> ptr = new edge(edgecount_++, sub_allocator(a_));
std::pair<edgeiter, bool> r = edges_.insert(ptr);
ptr.release();
return r.first;
}
I'm sure it's a stupid thing, but I can't figure out why MSVC10 can't match that prototype to that function.
And I think this code has an issue with const-ness, caused by containers of pointers, but I'll address that in a separate question.
Return value:
typename hypergraph<T,P,A>::node_iter
should be:
typename hypergraph<T,P,A>::nodeiter

Is there a library that provides a (directed) hypergraph implementation in C++?

I'm currently working on a project that enumerates the k-best solutions of a dynamic program using a directed hypergraph framework. My current implementation (in Python) works well, but is fairly slow. The algorithm performs a number of tight loops and a fair bit of recursion. I really think that I could realize significant speed improvements using a C++ implementation. However, after a fair bit of searching, I was unable to find any libraries that provide hypergraph implementations in C++ (specifically directed hypergraphs -- but I was unable to find even libraries for undirected hypergraphs). Does anyone know of such a library? It seems there was a GSoC proposal to bring hypergraph support to boost a few years ago, but it looks like it didn't really pan out.
I don't know of a library, but you could roll your own.
After messing around with the code for three days, I finally got a hypermap to compile without warnings on MSVC10 and GCC(http://ideone.com/oj46o).
Declarations:
#include <map>
#include <functional>
#include <memory>
template<class V, class E=int, class PV = std::less<V>, class PE=std::less<E>, class A=std::allocator<V> >
// V is data type of vertex
// E is identifier of Edge
// PV is node sorting predicate
// PE is edge sorting predicate
// A is allocator
class hypergraph {
#if _MSC_VER <= 1600
typedef A sub_allocator;
#else
typedef std::scoped_allocator_adaptor<A> sub_allocator;
#endif
public:
class vertex;
class edge;
typedef std::map<V, vertex, PV, sub_allocator> vertexset;
typedef std::map<E, edge, PE, sub_allocator> edgeset;
typedef typename vertexset::iterator vertexiter;
typedef typename edgeset::iterator edgeiter;
typedef typename vertexset::const_iterator cvertexiter;
typedef typename edgeset::const_iterator cedgeiter;
typedef std::reference_wrapper<const V> rwv;
typedef std::reference_wrapper<const E> rwe;
typedef std::reference_wrapper<vertex> rwvertex;
typedef std::reference_wrapper<edge> rwedge;
typedef std::map<rwv, rwvertex, PV, sub_allocator> ivertexset;
typedef std::map<rwe, rwedge, PE, sub_allocator> iedgeset;
typedef typename ivertexset::iterator ivertexiter;
typedef typename iedgeset::iterator iedgeiter;
typedef typename ivertexset::const_iterator civertexiter;
typedef typename iedgeset::const_iterator ciedgeiter;
class vertex {
friend class hypergraph<V,E,PV,PE,A>;
iedgeset edges_;
vertex(const PE&, const sub_allocator&);/* so users can'V make their own vertices*/
public:
vertex(vertex&&);
vertex& operator=(vertex&&);
iedgeset& edges();
const iedgeset& edges() const;
};
class edge {
friend class hypergraph<V,E,PV,PE,A>;
ivertexset vertices_;
ivertexiter head_;
edge(const PV&, const sub_allocator&); /* so users can'V make their own edges*/
public:
edge(edge&&);
edge& operator=(edge&&);
void set_head(const V& v);
const V* get_head() const;
ivertexset& vertices();
const ivertexset& vertices() const;
};
hypergraph(const PV& vertexpred=PV(), const PE& edgepred=PE(), const A& alloc=A());
std::pair<vertexiter,bool> add_vertex(V v=V());
std::pair<edgeiter,bool> add_edge(E e=E());
vertexiter erase_vertex(const vertexiter& iter);
vertexiter erase_vertex(const V& rhs);
edgeiter erase_edge(const edgeiter& iter);
edgeiter erase_edge(const E& rhs);
void connect(const E& e, const V& v);
void connect(const edgeiter& ei, const vertexiter& vi);
void disconnect(const E& e, const V& v);
void disconnect(const edgeiter& ei, const vertexiter& vi);
vertexset& vertices();
const vertexset& vertices() const;
edgeset& edges();
const edgeset& edges() const;
A get_allocator() const;
protected:
hypergraph(const hypergraph& rhs);
hypergraph& operator=(const hypergraph& rhs);
PV pv_;
PE pe_;
A a_;
vertexset vertices_;
edgeset edges_;
};
namespace std {
template<class E, class T, class R>
std::basic_ostream<E,T>& operator<<(std::basic_ostream<E,T>& s, const std::reference_wrapper<R>& r);
template<class E, class T, class R>
std::basic_istream<E,T>& operator>>(std::basic_istream<E,T>& s, std::reference_wrapper<R>& r);
}
Definitions:
#include <algorithm>
#include <cassert>
template<class V, class E, class PV, class PE, class A>
inline hypergraph<V,E,PV,PE,A>::vertex::vertex(const PE& pred, const typename hypergraph<V,E,PV,PE,A>::sub_allocator& alloc)
: edges_(pred, alloc)
{}
template<class V, class E, class PV, class PE, class A>
inline hypergraph<V,E,PV,PE,A>::vertex::vertex(typename hypergraph<V,E,PV,PE,A>::vertex&& rhs)
: edges_(std::move(rhs.edges_))
{}
template<class V, class E, class PV, class PE, class A>
inline typename hypergraph<V,E,PV,PE,A>::vertex& hypergraph<V,E,PV,PE,A>::vertex::operator=(typename hypergraph<V,E,PV,PE,A>::vertex&& rhs)
{
edges_ = std::move(rhs);
return *this;
}
template<class V, class E, class PV, class PE, class A>
inline typename hypergraph<V,E,PV,PE,A>::iedgeset& hypergraph<V,E,PV,PE,A>::vertex::edges()
{return edges_;}
template<class V, class E, class PV, class PE, class A>
inline const typename hypergraph<V,E,PV,PE,A>::iedgeset& hypergraph<V,E,PV,PE,A>::vertex::edges() const
{return edges_;}
template<class V, class E, class PV, class PE, class A>
inline hypergraph<V,E,PV,PE,A>::edge::edge(const PV& pred, const typename hypergraph<V,E,PV,PE,A>::sub_allocator& alloc)
: vertices_(pred, alloc)
, head_(vertices_.end())
{}
template<class V, class E, class PV, class PE, class A>
inline hypergraph<V,E,PV,PE,A>::edge::edge(edge&& rhs)
: vertices_(rhs.vertices_)
, head_(rhs.head_!=rhs.vertices_.end() ? vertices_.find(rhs.head_->first) : vertices_.end())
{}
template<class V, class E, class PV, class PE, class A>
inline typename hypergraph<V,E,PV,PE,A>::edge& hypergraph<V,E,PV,PE,A>::edge::operator=(typename hypergraph<V,E,PV,PE,A>::edge&& rhs)
{
vertices_ = std::move(rhs);
if (rhs.head_ != rhs.vertices_.end())
head_ = vertices_.find(rhs.head_->first);
else
head_ = vertices_.end();
return *this;
}
template<class V, class E, class PV, class PE, class A>
inline void hypergraph<V,E,PV,PE,A>::edge::set_head(const V& v)
{
ivertexiter iter = vertices_.find(std::ref(v));
assert(iter != vertices_.end());
head_ = iter;
}
template<class V, class E, class PV, class PE, class A>
inline const V* hypergraph<V,E,PV,PE,A>::edge::get_head() const
{return (head_ != vertices_.end() ? &head_->first.get() : NULL);}
template<class V, class E, class PV, class PE, class A>
inline const typename hypergraph<V,E,PV,PE,A>::ivertexset& hypergraph<V,E,PV,PE,A>::edge::vertices() const
{ return vertices_; }
template<class V, class E, class PV, class PE, class A>
inline typename hypergraph<V,E,PV,PE,A>::ivertexset& hypergraph<V,E,PV,PE,A>::edge::vertices()
{ return vertices_; }
template<class V, class E, class PV, class PE, class A>
inline hypergraph<V,E,PV,PE,A>::hypergraph(const PV& vertexpred, const PE& edgepred, const A& alloc)
:pv_(vertexpred)
,pe_(edgepred)
,a_(alloc)
,vertices_(vertexpred, a_)
,edges_(edgepred, a_)
{}
template<class V, class E, class PV, class PE, class A>
inline std::pair<typename hypergraph<V,E,PV,PE,A>::vertexiter, bool> hypergraph<V,E,PV,PE,A>::add_vertex(V v)
{ return vertices_.insert(std::pair<V, vertex>(std::move(v),vertex(pe_, a_))); }
template<class V, class E, class PV, class PE, class A>
inline std::pair<typename hypergraph<V,E,PV,PE,A>::edgeiter, bool> hypergraph<V,E,PV,PE,A>::add_edge(E e)
{ return edges_.insert(std::pair<E,edge>(std::move(e), edge(pv_, a_))); }
template<class V, class E, class PV, class PE, class A>
inline typename hypergraph<V,E,PV,PE,A>::vertexiter hypergraph<V,E,PV,PE,A>::erase_vertex(const typename hypergraph<V,E,PV,PE,A>::vertexiter& iter)
{
for(auto i = iter->edges().begin(); i != iter->edges().end(); ++i)
i->erase(*iter);
return vertices_.erase(iter);
}
template<class V, class E, class PV, class PE, class A>
inline typename hypergraph<V,E,PV,PE,A>::vertexiter hypergraph<V,E,PV,PE,A>::erase_vertex(const V& rhs)
{
vertexiter vi = vertices_.find(rhs);
assert(vi != vertices_.end());
vertex& v = vi->second;
for(auto i = v.edges().begin(); i != v.edges().end(); ++i)
i->second.get().vertices_.erase(std::ref(vi->first));
return vertices_.erase(vi);
}
template<class V, class E, class PV, class PE, class A>
inline typename hypergraph<V,E,PV,PE,A>::edgeiter hypergraph<V,E,PV,PE,A>::erase_edge(const typename hypergraph<V,E,PV,PE,A>::edgeiter& iter)
{
for(auto i = iter->vertices().begin(); i != iter->vertices().end(); ++i)
i->edges_.erase(*iter);
return edges_.erase(iter);
}
template<class V, class E, class PV, class PE, class A>
inline typename hypergraph<V,E,PV,PE,A>::edgeiter hypergraph<V,E,PV,PE,A>::erase_edge(const E& rhs)
{
edgeiter ei = edges_.find(rhs);
assert(ei != edges_.end());
edge& e = ei->second;
for(auto i = e.vertices().begin(); i != e.vertices().end(); ++i)
i->second.get().edges_.erase(std::ref(ei->first));
return edges_.erase(ei);
}
template<class V, class E, class PV, class PE, class A>
inline void hypergraph<V,E,PV,PE,A>::connect(const E& e, const V& v)
{
vertexiter vi = vertices_.find(v);
edgeiter ei = edges_.find(e);
assert(vi != vertices_.end());
assert(ei != edges_.end());
vi->second.edges_.insert(typename iedgeset::value_type(std::ref(ei->first), std::ref(ei->second)));
auto n = ei->second.vertices_.insert(typename ivertexset::value_type(std::ref(vi->first), std::ref(vi->second)));
if (ei->second.vertices_.size()==1)
ei->second.head_ = n.first;
}
template<class V, class E, class PV, class PE, class A>
inline void hypergraph<V,E,PV,PE,A>::connect(const typename hypergraph<V,E,PV,PE,A>::edgeiter& ei, const typename hypergraph<V,E,PV,PE,A>::vertexiter& vi)
{
assert(std::distance(vertices_.begin(), vi)>=0); //actually asserts that the iterator belongs to this container
assert(std::distance(edges_.begin(), ei)>=0); //actually asserts that the iterator belongs to this container
vi->edges_.insert(typename iedgeset::value_type(std::ref(ei->first), std::ref(ei->second)));
auto n = ei->vertices_.insert(typename ivertexset::value_type(std::ref(vi->first), std::ref(vi->second)));
if (ei->second.verticies_.size()==1)
ei->second.head_ = n.first;
}
template<class V, class E, class PV, class PE, class A>
inline void hypergraph<V,E,PV,PE,A>::disconnect(const E& e, const V& v)
{
edgeiter ei = edges_.find(e);
vertexiter vi = vertices_.find(v);
assert(ei != edges.end());
assert(vi != vertices_.end());
if (ei->head_.first == v) {
if (ei->head_ != ei->vertices.begin())
ei->head = ei->vertices.begin();
else
ei->head = ei->vertices.end();
}
ei->vertices_.erase(std::ref(vi->first));
vi->edges_.erase(std::ref(ei->first));
}
template<class V, class E, class PV, class PE, class A>
inline void hypergraph<V,E,PV,PE,A>::disconnect(const typename hypergraph<V,E,PV,PE,A>::edgeiter& ei, const typename hypergraph<V,E,PV,PE,A>::vertexiter& vi)
{
assert(std::distance(edges_.begin(), ei)>=0); //actually asserts that the iterator belongs to this container
assert(std::distance(vertices_.begin(), vi)>=0); //actually asserts that the iterator belongs to this container
if (ei->head_.first == vi->first) {
if (ei->head_ != ei->vertices.begin())
ei->head = ei->vertices.begin();
else
ei->head = ei->vertices.end();
}
ei->vertices_.erase(std::ref(vi->first));
vi->edges_.erase(std::ref(ei->first));
}
template<class V, class E, class PV, class PE, class A>
inline typename hypergraph<V,E,PV,PE,A>::vertexset& hypergraph<V,E,PV,PE,A>::vertices()
{ return vertices_;}
template<class V, class E, class PV, class PE, class A>
inline const typename hypergraph<V,E,PV,PE,A>::vertexset& hypergraph<V,E,PV,PE,A>::vertices() const
{ return vertices_;}
template<class V, class E, class PV, class PE, class A>
inline typename hypergraph<V,E,PV,PE,A>::edgeset& hypergraph<V,E,PV,PE,A>::edges()
{ return edges_;}
template<class V, class E, class PV, class PE, class A>
inline const typename hypergraph<V,E,PV,PE,A>::edgeset& hypergraph<V,E,PV,PE,A>::edges() const
{ return edges_;}
template<class V, class E, class PV, class PE, class A>
inline A hypergraph<V,E,PV,PE,A>::get_allocator() const
{ return a_;}
namespace std {
template<class E, class T, class R>
std::basic_ostream<E,T>& operator<<(std::basic_ostream<E,T>& s, const std::reference_wrapper<R>& r)
{return s << r.get();}
template<class E, class T, class R>
std::basic_istream<E,T>& operator>>(std::basic_istream<E,T>& s, std::reference_wrapper<R>& r)
{return s >> r.get();}
}
Note that this is not thoroughly tested, but it compiles and ran through my mini-suite without errors. (As shown in the IDEOne link). The Vertex types and the Edge identifiers can be any types you want, I tested with int verteces and string edge identifiers.
Hypergraphs are used for decoding in statistical machine translation. There are implementations of hypergraph data structures and algorithms in cdec decoder or relax-decode
One limitation is the edges in these implementation have multiple tails node but only a single head node.