Boost.ICL's interval_map
has two kinds of behaviors: +=
and insert
.
Both are useful in different context.
The first adds up values in common intersections of two existing intervals.
The second simply introduces the new value only in previously unassigned intervals (in previously assigned intervals the value is kept).
However I need a behavior that is subtly different, such that, in the example below instead of getting the undesired interval map (1.,2.)->1 , (2.5,3.)->3, (3.,5.)->2
I get instead the desired (1.,2.)->1 , (2.5,5.)->3
.
That is, that new inserted values replace old values?
How do I declare interval_map
to get that replacing behavior?
#include<boost/icl/interval_map.hpp>
int main(){
boost::icl::interval_map<double, int> joined_map;
joined_map.insert( std::make_pair(
boost::icl::interval<double>::open(1., 2.),
1
));
joined_map.insert( std::make_pair(
boost::icl::interval<double>::open(3., 5.),
2
));
joined_map.insert( std::make_pair(
boost::icl::interval<double>::open(2.5, 5.),
3
)); // this line doesn't replace the old value 2, it keeps it.
}
Bonus: Is that what boost::icl::map
is supposed to do? How do I use it?
EDIT 1: This is a more explicit and simplified sample code using C++11
#include<boost/icl/interval_map.hpp>
#include<iostream>
namespace icl = boost::icl;
using interval = icl::interval<double>;
int main(){
icl::interval_map<double, int> joined_map;
joined_map.insert({interval::open(1., 2.), 1});
joined_map.insert({interval::open(3., 5.), 2});
joined_map.insert({interval::open(2.5, 5.), 3});
// ^^^^ this line doesn't replace the old value 2! it keeps it.
for(auto e: joined_map) std::cout << e.first <<' '<< e.second <<'\n';
// prints: (1,2) 1 \\ (2.5,3] 3 \\ (3,5) 2
// desired: (1,2) 1 \\ (2.5,5] 3 // value 2 gone
}
EDIT 2: Complete solution based on @JorgeBellon's answer:
#include<boost/icl/interval_map.hpp>
#include<iostream>
namespace icl = boost::icl;
template <class Type>
struct inplace_replace{// : icl::identity_based_inplace_combine<Type>{
using first_argument_type = Type;
void operator()(Type& object, Type const& operand) const{object = operand;}
};
using interval = icl::interval<double>;
int main(){
icl::interval_map<
double, int,
icl::partial_enricher, // Unmapped intervals have unkown value;
// store identity values
std::less , // Comparator
inplace_replace //, // Combination operator // IMPORTANT!!
// icl::inplace_erasure//, // Extraction operator
// closed_interval<unsigned, std::less> // Interval type
> joined_map;
joined_map.add({interval::open(1. , 2.), 1}); // or joined_map+=std::make_pair(...)
joined_map.add({interval::open(3. , 5.), 2}); // IMPORTANT: USE add, NOT insert!!
joined_map.add({interval::open(2.5, 5.), 3});
// ^^^^ this line now replaces the old value 2
for(auto e: joined_map) std::cout << e.first <<' '<< e.second <<'\n';
// prints: (1,2) 1 \\ (2.5,5] 3 // value 2 gone
}