Semantic Engine C++ API

Utility Functions

By Gabriel Schine

This file describes the utility functions and classes used in the Semantic Engine.


1. Utility Functions and Classes
     1.1. Empty Class
     1.2. Type-Independent abs and max
     1.3. String Functions
     1.4. Transform Iterators
     1.5. Numerical Functions
     1.6. Maps Namespace


1. Utility Functions and Classes

This file contains a number of utility functions and classes that are used throughout the Semantic Engine. Each has its own section below.


1.1. Empty Class

An empty class. This can be thought of as the "NULL" type.

1. utility classes+={class empty_class {}; }
This macro is defined in definitions 1 and 7.
This macro is invoked in definition 13.


1.2. Type-Independent abs and max

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;
}
}
This macro is defined in definitions 2, 4, 5, 6, 9 and 10.
This macro is invoked in definition 13.


1.3. String Functions

The string functions require some includes:

3. includes+={
#include <string>
#include <sstream>
}
This macro is defined in definitions 3, 8 and 11.
This macro is invoked in definition 13.

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();
}
}
This macro is defined in definitions 2, 4, 5, 6, 9 and 10.
This macro is invoked in definition 13.

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();
}
}
This macro is defined in definitions 2, 4, 5, 6, 9 and 10.
This macro is invoked in definition 13.

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();
}
}
This macro is defined in definitions 2, 4, 5, 6, 9 and 10.
This macro is invoked in definition 13.


1.4. Transform Iterators

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) )
}
This macro is defined in definitions 1 and 7.
This macro is invoked in definition 13.

For the above we need some stuff from boost:

8. includes+={
#include <boost/iterator/transform_iterator.hpp>
}
This macro is defined in definitions 3, 8 and 11.
This macro is invoked in definition 13.


1.5. Numerical Functions

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;
}
}
This macro is defined in definitions 2, 4, 5, 6, 9 and 10.
This macro is invoked in definition 13.

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;
}
}
This macro is defined in definitions 2, 4, 5, 6, 9 and 10.
This macro is invoked in definition 13.


1.6. Maps Namespace

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
}
This macro is defined in definitions 3, 8 and 11.
This macro is invoked in definition 13.

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
}
This macro is invoked in definition 13.

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
}
This macro is attached to an output file.


End Of File