|
Semantic Engine C++ API
|
|
Utility Functions
|
|
By Gabriel Schine
|
| This file describes the utility functions and classes used in the Semantic Engine. |
|
This file contains a number of utility functions and classes that are used throughout the Semantic Engine. Each has its own section below. |
|
An empty class. This can be thought of as the "NULL" type. |
1. utility classes+={class empty_class {};
}
|
The following two functions perform what you would expect, but any type can be passed in. |
2. utility functions+={
template <class T>
inline T t_abs(const T& t) {
return t * (t<0?-1:1);
}
template <typename T>
inline T max(const T& one, const T& two) {
return one>two?one:two;
}
}
|
The string functions require some includes: |
3. includes+={
#include <string>
#include <sstream>
}
| to_string takes any type (which can be printed) and converts it into a std::string. |
4. utility functions+={
template <typename T>
inline std::string to_string(T v) {
std::stringstream strm;
strm << v;
return strm.str();
}
}
| join takes an iterator range and returns a string with all elements in the range in sequence with glue in between. |
5. utility functions+={
template <typename Iterator>
inline std::string join(Iterator i, Iterator i_end, std::string glue) {
std::stringstream strm;
unsigned int cnt = 0;
while(i != i_end) {
if (cnt++ > 0) strm << glue;
strm << *i;
++i;
}
return strm.str();
}
}
| unique_join does the same thing as join but will withold printing out the same element twice by using a std::set. |
6. utility functions+={
template <typename Iterator>
inline std::string unique_join(Iterator i, Iterator i_end, std::string glue) {
std::stringstream strm;
unsigned int cnt = 0;
std::set<typename Iterator::value_type> used;
while(i != i_end) {
if (used.count(*i)) {++i; continue;}
used.insert(*i);
if (cnt++ > 0) strm << glue;
strm << *i;
++i;
}
return strm.str();
}
}
|
The following two transform iterators take an iterator of std::pair elements and create a new iterator that will either hand back the first or second part of the pair. They can be created by calling the functions extract_keys() or extract_values(), or the equivalent extract_first_iterator() and extract_second_iterator(). |
7. utility classes+={
namespace detail {
// utility class to extract the first part of a pair
template <class P>
struct extract_first {
typedef typename P::first_type result_type;
const typename P::first_type & operator()(P &p) const { return p.first; }
};
// and for the second
template <class P>
struct extract_second {
typedef typename P::second_type result_type;
const typename P::second_type & operator()(P &p) const { return p.second; }
};
} // namespace detail
template <class I>
boost::transform_iterator<detail::extract_first<typename I::value_type>, I> extract_first_iterator(I it) {
return boost::transform_iterator<detail::extract_first<typename I::value_type>, I>(it, detail::extract_first<typename I::value_type>());
}
#define extract_keys(x) ( extract_first_iterator(x) )
template <class I>
boost::transform_iterator<detail::extract_second<typename I::value_type>, I> extract_second_iterator(I it) {
return boost::transform_iterator<detail::extract_second<typename I::value_type>, I>(it, detail::extract_second<typename I::value_type>());
}
#define extract_values(x) ( extract_second_iterator(x) )
}
|
For the above we need some stuff from boost: |
8. includes+={
#include <boost/iterator/transform_iterator.hpp>
}
| keep_within_range(num, min, max) will set num equal to either min or max if it does not fall between them. |
9. utility functions+={
template <typename Num>
inline void keep_within_range(Num &val, Num min, Num max) {
val = val<min?min:val>max?max:val;
}
}
| set_if_greater(compare, num) will set num equal to compare if compare is greater. |
10. utility functions+={
template <typename T>
inline void set_if_greater(const T &c, T &m) {
if (c > m) m = c;
}
}
|
The maps namespace exists to help with a smooth transition over to TR1, the proposed addition to the STL standard. These helper typedefs will choose between tr1::unordered_map types and std::map types, depending on what is necessary for the user. If TR1 is not available, the std:: namespace will always be used. |
11. includes+={
#include <map>
#include <boost/functional/hash.hpp>
#ifdef HAVE_TR1_UNORDERED_MAP
#include <tr1/unordered_map>
#endif
}
12. maps namespace={
namespace maps {
// ordered map -- will always use STLs std::map or std::multimap
template < typename Key,
typename Data,
class Compare = std::less<Key>,
class Alloc = std::allocator<std::pair<const Key, Data> > >
class ordered : public std::map<Key, Data, Compare, Alloc> {};
// ordered multi_map
template < typename Key,
typename Data,
class Compare = std::less<Key>,
class Alloc = std::allocator<std::pair<const Key, Data> > >
class ordered_multi : public std::multimap<Key, Data, Compare, Alloc> {};
// unordered map -- will use TR1 when available
template < typename Key,
typename Data,
class Hash = boost::hash<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<std::pair<const Key, Data> >,
bool cache_hash_code = false >
class unordered :
#ifdef HAVE_TR1_UNORDERED_MAP
public std::tr1::unordered_map<Key, Data, Hash, Pred, Alloc, cache_hash_code> {};
#else
public std::map<Key, Data, std::less<Key>, Alloc> {};
#endif
} // namespace maps
}
13. File: semantic/utility.hpp={
#ifndef _SEMANTIC_UTILITY_HPP_
#define _SEMANTIC_UTILITY_HPP_
includes
namespace semantic {
utility functions
utility classes
} // namespace semantic
maps namespace
#endif
}