|
Semantic Engine Core C++ API
|
|
By Gabriel Schine
|
| This file describes the Semantic Engine core API. All the main functionality of the Semantic Engine is described here, supplemented by the documentation in subgraph.hpp, which describes the sub-graph capabilities of the Semantic Engine. |
|
This file describes the Semantic Engine core API. All the main functionality of the Semantic Engine is described here, supplemented by the documentation in subgraph.hpp, which describes the sub-graph capabilities of the Semantic Engine. |
|
The Semantic Engine stores indices in a graph. A graph is a number of nodes and edges, with edges "connecting" two nodes together. The graph is bipartite in nature, directed and cannot have parallel edges. Any tools using the text-indexing features of the Semantic Engine can assume that a document node will always be connected to a term node, and vice versa. Heavy usage of the BOOST C++ Libraries (http://boost.org/) at the core of the Semantic Engine API offers stability and a common interface between BOOST libraries and the libraries of the Semantic Engine. The Semantic Engine API supplies extensions to the BGL (BOOST Graph Library). All functions are overloaded in the boost::* namespace. In this way, coders familiar with the BOOST API will easily transition into the Semantic API. |
|
Much of the power of the Semantic Engine comes from the leverage of policy-based programming. Policies are template arguments to the Semantic Engine base class (SEGraph) which alter core functionality. For SEGraph, the Storage Policy is chosen by passing a Storage Policy Selector type to the class. Storage Policies determine how an index will persist across program runs. A number of Storage Policies are included (see the files under storage/) and others can be easily written (see storage/concept.hpp for details). |
|
This class is at the core of the Semantic Engine. Its construction is a little complicated, so if you're trying to understand it, please try to read through this entire section. To access NoStoragePolicy and the se_graph_traits below we need to include the appropriate files: |
1. includes+={
#include <semantic/config.hpp>
#include <semantic/storage/none.hpp>
#include <semantic/properties.hpp>
}
2. SEGraph={
template <
class StoragePolicySelector = NoStoragePolicy,
class SEBase = StoragePolicy<
StoragePolicySelector,
typename se_graph_traits<StoragePolicySelector>::base_graph_type >
> class SEGraph : public SEBase
{
typedef SEGraph<StoragePolicySelector, SEBase> self_type;
typedef storage_traits<StoragePolicySelector> storage_traits;
typedef se_graph_traits<StoragePolicySelector> se_traits;
public:
SEGraph public scope
};
}
|
The SEGraph is built such that every class up the inheritance tree can be customized at type definition time. The class's parent type: SEBase is defined as the StoragePolicy template class. StoragePolicy classes take two template arguments, the first being the StoragePolicySelector. This type is an empty struct defined by a Storage Policy, coupled with a definition of StoragePolicy<StoragePolicySelector, SEBase>. The struct se_graph_traits lives in the semantic::* namespace and is defined in properties.hpp. se_graph_traits<StoragePolicySelector>::base_graph_type is a BOOST graph type. The SEBase template argument should never be altered. It was left open for future development. The following typedefs are made publicly available by the SEGraph class. |
3. SEGraph public scope+={
typedef SEBase base_type;
typedef typename se_traits::base_graph_type base_graph_type;
typedef StoragePolicySelector storage_policy_selector;
typedef base_type storage_policy_type;
}
|
The constructor is simple, and accepts only the name of the collection to which this graph should be tied. All operations performed on this graph will only affect the collection named in the constructor. For this reason, if multiple operations on multiple collections is desired, you must create multiple graph objects! |
4. SEGraph public scope+={
SEGraph() { SEGraph(""); }
explicit SEGraph(string name)
: base_type(), __refcount(0)
{
storage_policy_type::set_mirror_changes_to_storage(false);
set_property(*this, graph_name, name);
set_property(*this, graph_energy_hits, 1);
}
}
|
In order to access vertex and edge properties (see se_graph_traits<StoragePolicySelector>::vertex_properties_type and se_graph_traits<StoragePolicySelector>::edge_properties_type), we need to create accessor methods to get to them quickly. These methods exactly mirror those available in the BGL. |
5. SEGraph public scope+={
typename storage_traits::vertex_properties_type &
operator [] (typename se_traits::vertex_descriptor v) { return (get(vertex_bundle, *this))[v]; }
const typename storage_traits::vertex_properties_type &
operator [] (typename se_traits::vertex_descriptor v) const { return (get(vertex_bundle, *this))[v]; }
typename storage_traits::edge_properties_type &
operator [] (typename se_traits::edge_descriptor e) { return (get(edge_bundle, *this))[e]; }
const typename storage_traits::edge_properties_type &
operator [] (typename se_traits::edge_descriptor e) const { return (get(edge_bundle, *this))[e]; }
}
|
And this one allows you to get the name of the collection to which this graph is tied. |
6. SEGraph public scope+={
std::string collection() const {
return get_property(*this, graph_name);
}
}
|
The following method is supplied as a convenience method. The WeightingPolicy defines the algorithm to use to apply weights to the supplied WeightMap. More information on Weighting Policies can be found in the weighting/ subdirectory. The WeightMap must be a BOOST property map keyed by edge. |
7. SEGraph public scope+={
template <class WeightingPolicy, class WeightMap>
void populate_weight_map(WeightingPolicy weighting, WeightMap w) {
typedef typename WeightingPolicy::weight_type weight_type;
typedef typename se_traits::edge_descriptor Edge;
typedef typename se_traits::vertex_iterator iterator;
// make sure we were passed the right kind of WeightMap
function_requires< WritablePropertyMapConcept<WeightMap, Edge> >();
BOOST_STATIC_ASSERT((boost::is_same<typename boost::property_traits<WeightMap>::value_type, weight_type>::value));
// go through all the vertices and apply our weighting algorithm
iterator vi, vi_end;
for(boost::tie(vi, vi_end) = vertices(*this); vi != vi_end; ++vi) {
weighting.apply_weights(*vi, *this, w);
}
}
}
8. SEGraph public scope+={
void clear() {
storage_policy_type::will_clear();
base_type::clear();
storage_policy_type::did_clear();
}
}
| clear() overrides the function of the same name in the BGL. Here the Storage Policy gets a chance to perform any operations before and after the actual clearing of the in-memory graph. |
|
The following methods are helpers that make it easy to apply pruning operations to a graph, its vertices or edges. See the file pruning.hpp for example (and useful!) pruning methods. These methods make heavy use of the BOOST graph iteration macros: |
9. includes+={
#include <boost/graph/iteration_macros.hpp>
}
10. SEGraph public scope+={
template <class Functor>
void apply_to_graph(Functor f) {
f(*this);
}
}
|
For apply_to_graph(), Functor must have an operator () method defined and templated on a single parameter (the Graph type). |
11. SEGraph public scope+={
template <class Functor>
void apply_to_all_vertices(Functor f) {
BGL_FORALL_VERTICES_T(v, (*this), base_graph_type) f(v, *this);
}
}
|
For apply_to_all_vertices(), Functor must have an operator () method defined and templated on at least the Graph (second) parameter. The first will be a se_graph_traits<Graph>::vertex_descriptor, and can be templated out of convenience if desired. |
12. SEGraph public scope+={
template <class Functor>
void apply_to_all_edges(Functor f) {
BGL_FORALL_EDGES_T(e, (*this), base_graph_type) f(e, *this);
}
}
|
For apply_to_all_edges(), Functor must have an operator () method defined and be templated on at least the second parameter. The first will be a se_graph_traits<Graph>::edge_descriptor and can be templated out of convenience. |
|
Like in the BGL, there are a host of non-member functions that act on the SEGraph class. The names and interfaces are taken directloy frmo the BGL. Some functions that can be called safely from the BGL cannot be used with SEGraph. Those functions will throw an exception if called. All functions that can be called on a BOOST graph can also be called on an SEGraph. |
|
add_vertex will add a vertex to the graph and return
the vertex_descriptor. You must supply
a vertex_properties_type struct to the function. (see
se_graph_traits<Graph>::vertex_properties_type)
Before adding, it will ask the Storage Policy if it should proceed. The Storage Policy might say no if, for example, a vertex with similar properties already exists, it might just update the properties already in the graph and avoid adding a new vertex. After adding, it will tell the Storage Policy that a new vertex was just added. |
13. non-member functions+={
template <class StoragePolicySelector, class SEBase>
inline typename se_graph_traits<StoragePolicySelector>::vertex_descriptor
add_vertex(const typename storage_traits<StoragePolicySelector>::vertex_properties_type &p, SEGraph<StoragePolicySelector, SEBase> &g)
{
typedef typename se_graph_traits<StoragePolicySelector>::base_graph_type base_type;
typedef typename graph_traits<base_type>::vertex_descriptor Vertex;
typedef typename storage_traits<StoragePolicySelector>::vertex_properties_type vertex_properties_type;
base_type& base_g = static_cast<base_type&>(g);
Vertex v;
bool should_add;
boost::tie(should_add, v) = g.will_add_vertex(p);
// should we add this vertex?
if (should_add) {
v = boost::add_vertex(p, base_g);
g.did_add_vertex(v, p);
}
return v;
}
// THIS FUNCTION SHOULD NOT BE CALLED! USE add_vertex(properties, graph) INSTEAD
template <class StoragePolicySelector, class SEBase>
inline void
add_vertex(SEGraph<StoragePolicySelector, SEBase> &g)
{
struct DoNotUseThisMethodException {};
throw DoNotUseThisMethodException();
}
}
|
add_edge will add an edge to the graph between two vertices. A set
of edge_properties_type will be attached to the edge. Like in
add_vertex, the Storage Policy will be asked if the edge
should be added or not. A std::pair<edge_descriptor,bool> will be
returned. If the bool is false, it means that the edge was
not added due to there already being an edge between those vertices, or
the Storage Policy denying edge addition.
The Storage Policy will be notified of edge addition after the fact, as well. |
14. non-member functions+={
template <class StoragePolicySelector, class SEBase>
inline std::pair<typename se_graph_traits<StoragePolicySelector>::edge_descriptor, bool>
add_edge(
typename se_graph_traits<StoragePolicySelector>::vertex_descriptor u,
typename se_graph_traits<StoragePolicySelector>::vertex_descriptor v,
const typename storage_traits<StoragePolicySelector>::edge_properties_type &p,
SEGraph<StoragePolicySelector, SEBase> &g)
{
typedef se_graph_traits<StoragePolicySelector> graph_traits;
typedef typename graph_traits::vertex_descriptor Vertex;
typedef typename graph_traits::edge_descriptor Edge;
typedef typename graph_traits::base_graph_type base_type;
base_type& base_g = static_cast<base_type&>(g);
std::pair<Edge, bool> edge_result;
if (g.will_add_edge(u, v, p)) {
edge_result = boost::add_edge(u, v, p, base_g);
// if it already existed, update the properties
if (edge_result.second == false) {
g[edge_result.first] = p;
}
g.did_add_edge(edge_result.first, edge_result.second, u, v, p);
} else {
edge_result = std::make_pair(Edge(), false);
}
return edge_result;
}
// THIS FUNCTION SHOULD NOT BE CALLED! USE add_edge(vertex, vertex, properties, graph) INSTEAD
template <class StoragePolicySelector, class SEBase>
inline std::pair<typename se_graph_traits<StoragePolicySelector>::edge_descriptor, bool>
add_edge(
typename se_graph_traits<StoragePolicySelector>::vertex_descriptor u,
typename se_graph_traits<StoragePolicySelector>::vertex_descriptor v,
SEGraph<StoragePolicySelector, SEBase> &g)
{
struct DoNotUseThisMethodException {};
throw DoNotUseThisMethodException();
}
}
|
This function is identical to add_edge, except that if the edge already exists, instead of updating the properties, the property's strength member is increased by the value in the new property's field. |
15. non-member functions+={
template <class StoragePolicySelector, class SEBase>
inline std::pair<typename se_graph_traits<StoragePolicySelector>::edge_descriptor, bool>
add_or_strengthen_edge(
typename se_graph_traits<StoragePolicySelector>::vertex_descriptor u,
typename se_graph_traits<StoragePolicySelector>::vertex_descriptor v,
const typename storage_traits<StoragePolicySelector>::edge_properties_type &p,
SEGraph<StoragePolicySelector, SEBase> &g)
{
typedef se_graph_traits<StoragePolicySelector> graph_traits;
typedef typename graph_traits::vertex_descriptor Vertex;
typedef typename graph_traits::edge_descriptor Edge;
typedef typename graph_traits::base_graph_type base_type;
base_type& base_g = static_cast<base_type&>(g);
std::pair<Edge, bool> edge_result;
if (g.will_add_edge(u, v, p)) {
edge_result = boost::add_edge(u, v, p, base_g);
// if it already exists, strengthen the edge
if (edge_result.second == false) {
typename graph_traits::edge_properties_type old_p = g[edge_result.first];
g[edge_result.first] = p;
g[edge_result.first].strength += old_p.strength;
}
g.did_add_edge(edge_result.first, edge_result.second, u, v, g[edge_result.first]);
} else {
edge_result = std::make_pair(Edge(), false);
}
return edge_result;
}
}
|
remove_edge has three invokations: by edge_descriptor,
by two vertex_descriptors, or by out_edge_iterator.
All are functionally equivalent.
The Storage Policy will be told of edge removal before and after the fact. |
16. non-member functions+={
template <class StoragePolicySelector, class SEBase>
inline void
remove_edge(
typename se_graph_traits<StoragePolicySelector>::vertex_descriptor u,
typename se_graph_traits<StoragePolicySelector>::vertex_descriptor v,
SEGraph<StoragePolicySelector, SEBase> &g)
{
typedef se_graph_traits<StoragePolicySelector> graph_traits;
typedef typename graph_traits::edge_descriptor Edge;
typedef typename graph_traits::base_graph_type base_type;
base_type& base_g = static_cast<base_type&>(g);
g.will_remove_edge(u, v);
boost::remove_edge(u, v, base_g);
g.did_remove_edge(u, v);
}
template <class StoragePolicySelector, class SEBase>
inline void
remove_edge(
typename se_graph_traits<StoragePolicySelector>::edge_descriptor e,
SEGraph<StoragePolicySelector, SEBase> &g)
{
typedef se_graph_traits<StoragePolicySelector> graph_traits;
typedef typename graph_traits::vertex_descriptor Vertex;
typedef typename graph_traits::edge_descriptor Edge;
typedef typename graph_traits::base_graph_type base_type;
base_type& base_g = static_cast<base_type&>(g);
Vertex u,v;
u = boost::source(e, base_g);
v = boost::target(e, base_g);
g.will_remove_edge(u, v);
boost::remove_edge(e, base_g);
g.did_remove_edge(u, v);
}
template <class StoragePolicySelector, class SEBase>
inline void
remove_edge(
typename se_graph_traits<StoragePolicySelector>::out_edge_iterator i,
SEGraph<StoragePolicySelector, SEBase>& g)
{
typedef se_graph_traits<StoragePolicySelector> graph_traits;
typedef typename graph_traits::vertex_descriptor Vertex;
typedef typename graph_traits::edge_descriptor Edge;
typedef typename graph_traits::base_graph_type base_type;
Edge e = *i;
base_type& base_g = static_cast<base_type&>(g);
Vertex u,v;
u = boost::source(e, base_g);
v = boost::target(e, base_g);
g.will_remove_edge(u, v);
boost::remove_edge(i, base_g);
g.did_remove_edge(u, v);
}
}
| remove_out_edge_if takes a vertex and a predicate. It iterates over the out edges of the vertex and removes any of them if Predicate(edge) resolves to true. Again, the Storage Policy will be told before and after each edge removal. |
17. non-member functions+={
template <class StoragePolicySelector, class SEBase, class Predicate>
inline void
remove_out_edge_if(
typename se_graph_traits<StoragePolicySelector>::vertex_descriptor u,
Predicate predicate,
SEGraph<StoragePolicySelector, SEBase> &g)
{
typedef se_graph_traits<StoragePolicySelector> graph_traits;
typedef typename graph_traits::vertex_descriptor Vertex;
typedef typename graph_traits::edge_descriptor Edge;
typedef typename graph_traits::base_graph_type base_type;
typedef typename graph_traits::out_edge_iterator iterator;
base_type& base_g = static_cast<base_type&>(g);
std::vector<Edge> to_remove;
iterator ei, ei_end;
for(boost::tie(ei, ei_end) = boost::out_edges(u, base_g); ei != ei_end; ++ei) {
if (predicate(*ei)) to_remove.push_back(*ei);
}
for(typename graph_traits::edges_size_type i = 0; i < to_remove.size(); i++) {
Vertex v;
v = boost::target(to_remove[i], base_g);
g.will_remove_edge(u, v);
boost::remove_edge(to_remove[i], base_g);
g.did_remove_edge(u, v);
}
}
}
|
This method is overloaded from the boost such that it will be impossible to call on an SEGraph. Since our graphs are directed, the concept of "in edges" doesn't really exist. |
18. non-member functions+={
template <class StoragePolicySelector, class SEBase, class Predicate>
inline void
remove_in_edge_if(
typename se_graph_traits<StoragePolicySelector>::vertex_descriptor,
Predicate, SEGraph<StoragePolicySelector, SEBase>&)
{
struct DoNotUseThisMethodException {};
throw DoNotUseThisMethodException();
}
}
|
This method removes all edges in the graph that match Predicate. The Storage Policy will be notified before and after each edge removal. |
19. non-member functions+={
template <class StoragePolicySelector, class SEBase, class Predicate>
inline void
remove_edge_if(
Predicate predicate,
SEGraph<StoragePolicySelector, SEBase> &g)
{
typedef se_graph_traits<StoragePolicySelector> graph_traits;
typedef typename graph_traits::vertex_descriptor Vertex;
typedef typename graph_traits::edge_descriptor Edge;
typedef typename graph_traits::base_graph_type base_type;
typedef typename graph_traits::edge_iterator iterator;
base_type& base_g = static_cast<base_type&>(g);
std::vector<Edge> to_remove;
iterator ei, ei_end;
for(boost::tie(ei, ei_end) = boost::edges(base_g); ei != ei_end; ++ei) {
if (predicate(*ei)) to_remove.push_back(*ei);
}
for(typename graph_traits::edges_size_type i = 0; i < to_remove.size(); i++) {
Vertex u, v;
u = boost::source(to_remove[i], base_g);
v = boost::target(to_remove[i], base_g);
g.will_remove_edge(u, v);
boost::remove_edge(to_remove[i], base_g);
g.did_remove_edge(u, v);
}
}
}
|
This method will clear all edges to and from the given vertex from the graph. The Storage Policy will be notified before and after the vertex is cleared. |
20. non-member functions+={
template <class StoragePolicySelector, class SEBase>
inline void
clear_vertex(
typename se_graph_traits<StoragePolicySelector>::vertex_descriptor u,
SEGraph<StoragePolicySelector, SEBase> &g)
{
typedef se_graph_traits<StoragePolicySelector> graph_traits;
typedef typename graph_traits::base_graph_type base_type;
base_type& base_g = static_cast<base_type&>(g);
g.will_clear_vertex(u);
boost::clear_vertex(u, base_g);
g.did_clear_vertex(u);
}
}
|
This method takes a vertex and clears all the edges coming out of the vertex. The Storage Policy will be notified before and after each edge removal. |
21. non-member functions+={
template <class StoragePolicySelector, class SEBase>
inline void
clear_out_edges(
typename se_graph_traits<StoragePolicySelector>::vertex_descriptor u,
SEGraph<StoragePolicySelector, SEBase> &g)
{
typedef se_graph_traits<StoragePolicySelector> graph_traits;
typedef typename graph_traits::vertex_descriptor Vertex;
typedef typename graph_traits::edge_descriptor Edge;
typedef typename graph_traits::base_graph_type base_type;
typedef typename graph_traits::out_edge_iterator iterator;
base_type& base_g = static_cast<base_type&>(g);
iterator ei, ei_end;
boost::tie(ei, ei_end) = boost::out_edges(u, base_g);
std::vector<Edge> to_remove(ei, ei_end);
for(typename graph_traits::edges_size_type i = 0; i < to_remove.size(); i++) {
Vertex v;
v = boost::target(to_remove[i], base_g);
g.will_remove_edge(u, v);
boost::remove_edge(to_remove[i], base_g);
g.did_remove_edge(u, v);
}
}
}
|
This method should never be called and is overloaded just to make sure. |
22. non-member functions+={
template <class StoragePolicySelector, class SEBase>
inline void
clear_in_edges(
typename se_graph_traits<StoragePolicySelector>::vertex_descriptor,
SEGraph<StoragePolicySelector, SEBase>&)
{
struct DoNotUseThisMethodException {};
throw DoNotUseThisMethodException();
}
}
| remove_vertex will remove a vertex from the graph. The Storage Policy will be notified before and after the vertex removal. |
23. non-member functions+={
template <class StoragePolicySelector, class SEBase>
inline void
remove_vertex(
typename se_graph_traits<StoragePolicySelector>::vertex_descriptor u,
SEGraph<StoragePolicySelector, SEBase> &g)
{
typedef se_graph_traits<StoragePolicySelector> graph_traits;
typedef typename graph_traits::base_graph_type base_type;
base_type& base_g = static_cast<base_type&>(g);
typename storage_traits<StoragePolicySelector>::vertex_properties_type vp = g[u];
g.will_remove_vertex(u, vp);
boost::remove_vertex(u, base_g);
g.did_remove_vertex(vp);
}
}
| merge_vertices will merge the second vertex into the first. The second vertex will no longer exist, and all the edges will be copied over to the first vertex. |
24. non-member functions+={
template <class StoragePolicySelector, class SEBase>
inline void
merge_vertices(
typename se_graph_traits<StoragePolicySelector>::vertex_descriptor u,
typename se_graph_traits<StoragePolicySelector>::vertex_descriptor v,
SEGraph<StoragePolicySelector, SEBase> &g)
{
typedef se_graph_traits<StoragePolicySelector> graph_traits;
typedef typename graph_traits::base_graph_type base_type;
base_type& base_g = static_cast<base_type&>(g);
// step one: take all the edges from #2 and run into #1 (this is slow...)
typename graph_traits::edge_iterator ei, ei_end;
for(boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) {
if (source(*ei, g) == v || target(*ei, g) == v) {
// copy the edge to u
typename graph_traits::edge_properties_type &ep = g[*ei], nep;
nep.strength = ep.strength;
if (source(*ei, g) == v) {
add_edge(u, target(*ei, g), nep, g);
} else {
add_edge(source(*ei, g), u, nep, g);
}
}
}
// now remove the old vertex
remove_vertex(v, g);
}
}
| either_edge does not exist in BOOST but is provided here for convenience. This method takes two vertices: u and v and returns a std::pair<edge_descriptor,bool>. bool will be true if an edge from either u->v or v->u is found, and false otherwise. |
25. non-member functions+={
template <class StoragePolicySelector, class SEBase>
inline std::pair<typename se_graph_traits<StoragePolicySelector>::edge_descriptor, bool>
either_edge(
typename se_graph_traits<StoragePolicySelector>::vertex_descriptor u,
typename se_graph_traits<StoragePolicySelector>::vertex_descriptor v,
SEGraph<StoragePolicySelector, SEBase> &g)
{
typedef se_graph_traits<StoragePolicySelector> graph_traits;
typedef typename graph_traits::edge_descriptor edge_desc;
std::pair<edge_desc, bool> edge_exists = edge(u, v, g);
if (edge_exists.second) return edge_exists;
return edge(v, u, g);
}
}
|
This is defined to allow an SEGraph to be output to a std::ostream. |
26. global functions+={
template<class S, class B>
std::ostream & operator<<(std::ostream &o, const SEGraph<S,B> &g) {
o << "graph: " << get_property(g, graph_name) << " (v:" << num_vertices(g) << " e:" << num_edges(g) << ")" << std::endl;
typename se_graph_traits<S>::vertex_iterator vi, vi_end;
for(boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) {
typename se_graph_traits<S>::adjacency_iterator ai, ai_end;
o << g[*vi].content << "(" << g[*vi].type_major << "): ";
for(boost::tie(ai, ai_end) = adjacent_vertices(*vi, g); ai != ai_end; ++ai) {
o << g[*ai].content << "(" << g[*ai].type_major << ") ";
}
o << std::endl;
}
return o;
}
}
|
You can use the following class to manage index files. It allows manipulation of collections without creating an SEGraph object tied to a collection. |
27. index manager+={
template <class StoragePolicySelector>
class index_manager : public StoragePolicy<StoragePolicySelector, empty_class>
{
typedef StoragePolicy<StoragePolicySelector, empty_class> SEBase;
public:
std::vector<std::string> list_collections() {
std::vector<std::string> collections;
SEBase::get_collections_list(back_inserter(collections));
return collections;
}
void rename_collection(std::string oldname, std::string newname) {
SEBase::rename_collection(oldname, newname);
}
void remove_collection(std::string name) {
SEBase::remove_collection(name);
}
}; // index_manager
}
| And for backwards compatibility: |
28. index manager+={
template <class S>
class StorageInfoQuery : public index_manager<S> {};
}
|
If smart pointers are to be used with the SEGraph class, a convenience reference counter variable has been included in the public scope and is automatically initialized to 0 on construction. |
29. SEGraph public scope+={unsigned int __refcount;
}
|
Furthermore, if using BOOST's intrusive_ptr class, the helper functions necessary to do so are defined here: |
30. BOOST intrusive_ptr functions={
namespace boost {
template <class S, class B>
inline void intrusive_ptr_add_ref(SEGraph<S,B> * p) {
++(p->__refcount);
}
template <class S, class B>
inline void intrusive_ptr_release(SEGraph<S,B> * p) {
if (--(p->__refcount) == 0)
delete p;
}
} // namespace boost
}
31. File: semantic/semantic.hpp={
#ifndef _SEMANTIC_HPP_
#define _SEMANTIC_HPP_
includes
using std::string;
using std::vector;
using std::set;
using namespace boost;
using namespace semantic;
namespace semantic {
SEGraph
index manager
} // namespace semantic
namespace boost {
non-member functions
} // namespace boost
global functions
BOOST intrusive_ptr functions
#endif /* _SEMANTIC_HPP_ */
}