I am trying to use boost::icl::interval_map
with a custom interval MyInterval
and closed bounds (interval_bounds::static_closed
), similarly to interval_set
example. This construct is, however, throwing the following error:
---- Map State -----------------
[0,10] - A
prog.exe: /opt/wandbox/boost-1.71.0/gcc-head/include/boost/icl/interval_base_map.hpp:557: boost::icl::interval_base_map<SubType, DomainT, CodomainT, Traits, Compare, Combine, Section, Interval, Alloc>::iterator boost::icl::interval_base_map<SubType, DomainT, CodomainT, Traits, Compare, Combine, Section, Interval, Alloc>::gap_insert(boost::icl::interval_base_map<SubType, DomainT, CodomainT, Traits, Compare, Combine, Section, Interval, Alloc>::iterator, const interval_type&, const codomain_type&) [with Combiner = boost::icl::inplace_plus<std::__cxx11::basic_string<char> >; SubType = boost::icl::interval_map<int, std::__cxx11::basic_string<char>, boost::icl::partial_absorber, std::less, boost::icl::inplace_plus, boost::icl::inter_section, MyInterval>; DomainT = int; CodomainT = std::__cxx11::basic_string<char>; Traits = boost::icl::partial_absorber; Compare = std::less; Combine = boost::icl::inplace_plus; Section = boost::icl::inter_section; Interval = MyInterval; Alloc = std::allocator; boost::icl::interval_base_map<SubType, DomainT, CodomainT, Traits, Compare, Combine, Section, Interval, Alloc>::iterator = std::_Rb_tree<MyInterval, std::pair<const MyInterval, std::__cxx11::basic_string<char> >, std::_Select1st<std::pair<const MyInterval, std::__cxx11::basic_string<char> > >, boost::icl::exclusive_less_than<MyInterval>, std::allocator<std::pair<const MyInterval, std::__cxx11::basic_string<char> > > >::iterator; boost::icl::interval_base_map<SubType, DomainT, CodomainT, Traits, Compare, Combine, Section, Interval, Alloc>::interval_type = MyInterval; boost::icl::interval_base_map<SubType, DomainT, CodomainT, Traits, Compare, Combine, Section, Interval, Alloc>::codomain_type = std::__cxx11::basic_string<char>]: Assertion `this->_map.find(inter_val) == this->_map.end()' failed.
I have noticed that either (1) using another interval_bounds
type, e.g. static_open
, or (2) using default interval_type
, i.e.interval<int>::closed()
, works just fine. Using MyInterval
and static_closed
bounds combination seems to be the problem. What configuration am I missing or what have I done incorrectly?
Code: below or Wandbox.
Boost: 1.71
GCC: 9.2.0.
#ifndef MY_INTERVAL_HXX
#define MY_INTERVAL_HXX
#include <iostream>
#include <boost/icl/interval_map.hpp>
using namespace std;
using namespace boost::icl;
class MyInterval
{
public:
MyInterval(): _first(), _past(){}
MyInterval(int lo, int up): _first(lo), _past(up){}
int first()const{ return _first; }
int past ()const{ return _past; }
private:
int _first, _past;
};
namespace boost { namespace icl
{
template<>
struct interval_traits<MyInterval>
{
typedef MyInterval interval_type;
typedef int domain_type;
typedef std::less<int> domain_compare;
static interval_type construct(const domain_type &lo, const domain_type &up)
{ return interval_type(lo, up); }
static domain_type lower(const interval_type &inter_val) { return inter_val.first(); }
static domain_type upper(const interval_type &inter_val) { return inter_val.past(); }
};
template<>
struct interval_bound_type<MyInterval>
{
typedef interval_bound_type type;
BOOST_STATIC_CONSTANT(bound_type, value = interval_bounds::static_closed);
};
}} // namespace boost icl
#endif
#include <iostream>
#include <cstdlib>
#include <string>
#include <boost/icl/interval_map.hpp>
#include "MyInterval.hxx"
using namespace boost::icl;
int main()
{
interval_map <int
, std::string
, partial_absorber
, std::less // ICL_COMPARE_INSTANCE(ICL_COMPARE_DEFAULT, int),
, inplace_plus // ICL_COMBINE_INSTANCE(inplace_plus, int),
, inter_section // ICL_SECTION_INSTANCE(inter_section, int),
, MyInterval
> imap;
std::string A("A");
std::string B("B");
std::string C("C");
auto Ai = MyInterval(0,10);
//auto Ai = interval<int>::closed(0,10);
auto Bi = MyInterval(5,15);
//auto Bi = interval<int>::closed(5,15);
auto Ci = MyInterval(7,12);
//auto Ci = interval<int>::closed(7,12);
imap += std::make_pair(Ai, A);
std::cout << "---- Map State -----------------" << std::endl;
for (const auto& val : imap) { std::cout << val.first << " - " << val.second << std::endl; }
std::cout << std::endl;
imap += std::make_pair(Bi, B);
std::cout << "---- Map State -----------------" << std::endl;
for (const auto& val : imap) { std::cout << val.first << " - " << val.second << std::endl; }
std::cout << std::endl;
imap += std::make_pair(Ci, C);
std::cout << "---- Map State -----------------" << std::endl;
for (const auto& val : imap) { std::cout << val.first << " - " << val.second << std::endl; }
std::cout << std::endl;
return 0;
}
---- Map State -----------------
[0,10] - A
---- Map State -----------------
[0,5) - A
[5,10] - AB
(10,15] - B
---- Map State -----------------
[0,5) - A
[5,7) - AB
[7,10] - ABC
(10,12] - BC
(12,15] - B
This is the same problem a friend of mine had once.
The problem is that the default constructor of your custom class is not right. I'm not sure if the boost documentation says this, but it must produce an invalid range. In your case, the default constructor is producing a range [0, 0]
.
Basically, the way the library checks if a range is valid is based on the type of bounds:
static_open
, for instance the function that checks if the interval is invalid is equivalent to upper() <= lower()
. That is why it works in your code: 0 <= 0 -> true
.static_closed
, the function that checks if the interval is invalid is equivalent to upper() < lower()
.In order for it to work, you need to change the default constructor to produce something where upper() < lower()
.
Change the default constructor to something like:
MyInterval() : _first(0), _past(-1) {}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With