
#include <boost/icl/interval_map.hpp>
#include <iostream>

using namespace boost::icl;

// interval_map combiner functor: assigns new value if key exists
template <class Type>
struct inplace_replace : identity_based_inplace_combine<Type> {
  void operator()(Type &object, const Type &operand) const { object = operand; }
};

template<>
inline std::string unary_template_to_string<inplace_replace>::apply() {
	return "=";
}

/* When adding, if interval exists, replaces value.
 * When subtracting, if interval exists, removes value.
 */
using ival_map =
    interval_map<unsigned,         // Key
                 unsigned,         // Value
                 partial_enricher, // Unmapped intervals have unkown value;
                                   // store identity values
                 std::less,        // Comparator
                 inplace_replace,  // Combination operator
                 inplace_erasure,  // Extraction operator
                 closed_interval<unsigned, std::less> // Interval type
                 >;

using ival = ival_map::interval_type;

std::ostream &operator<<(std::ostream &os, const ival_map &m) {
  for (auto &entry : m) {
    os << entry.first << " : " << entry.second << "\n";
  }
  return os;
}

int main() {
  ival_map m;
  
  m.add(std::make_pair(ival(0, 9), 1));
  std::cout << m << "\n\n";

  m.add(std::make_pair(ival(3, 6), 3));
  std::cout << m << "\n\n";

  m.add(std::make_pair(ival(3, 6), 1));
  std::cout << m << "\n\n";

  m.subtract(std::make_pair(ival(3, 6), 3));
  std::cout << m << "\n\n";

  m.subtract(std::make_pair(ival(3, 6), 1));
  std::cout << m << "\n\n";

  return 0;
}
