Opened 9 years ago

Closed 7 years ago

#9501 closed Bugs (fixed)

interval_set uses std::set with non strict weak ordering

Reported by: Tamás Kenéz <tamas.kenez@…> Owned by: Joachim Faulhaber
Milestone: To Be Determined Component: ICL
Version: Boost 1.55.0 Severity: Showstopper
Keywords: icl interval_set insert clang llvm set ordering Cc: tamas.kenez@…

Description

This program fails with clang's own LLVM STL implementation (libc++)

#include <boost/icl/interval_set.hpp> void t1() {

correct output: [15 43)

invalid output (mac, xcode 5.0.2, w/standard lib: "libc++ (LLVM)") [15 31) [30 43)

typedef boost::icl::interval_set<int> IVS; typedef boost::icl::discrete_interval<int> IV;

IVS ivs; ivs.insert(IV(20, 21)); ivs.insert(IV(30, 43)); ivs.insert(IV(15, 31));

for(auto it = ivs.begin(); it != ivs.end(); ++it)

printf("[%d %d)\n", it->lower(), it->upper());

}

Reason:

interval_set's underlying std::set container requires a strict weak ordering. interval_set uses an "overlap-free less" (icl/detail/exclusive_less_than.hpp) which is not strict weak (that is, !(a<b)&&!(b<a) is not transitive). Therefore, behaviour of std::set::insert becomes undefined. With clang's libc++, it is different than the one excepted by the icl.

std::set test case mimicking what's happening under the hood in interval_set::insert:

struct MIV {

MIV(int a, int b) :lo(a), hi(b) {}

int lo, hi;

equivalent to the intervalset's overlap-free less in boost::icl::exclusive_less_than bool operator<(const MIV& y) const {

return hi <= y.lo;

}

};

#include <set> void t2() {

output when icl works: it: [30-43), bool: 0

output when icl fails (mac, xcode 5.0.2, w/standard lib: "libc++ (LLVM)") it: [20-21), bool: 0

typedef std::set<MIV> MSET; MSET ms;

ms.insert(MIV(20, 21)); ms.insert(MIV(30, 43));

auto itb = ms.insert(MIV(15, 31));

printf("it: [%d-%d), bool: %d\n", itb.first->lo, itb.first->hi, itb.second);

}

Change History (4)

comment:1 by Tamás Kenéz <tamas.kenez@…>, 9 years ago

Cc: tamas.kenez@… added

comment:2 by Ivan Romanenko <viva.cpp@…>, 9 years ago

Also found the same problem. When ICL use boost::container::flat_set instead of std::set.

Because implementation of insertion algorithm in boost::container::flat_set differs with std::set and boost::container::set.

PS. Same problem with interval_map and std::map

comment:3 by tvk.boost@…, 8 years ago

Severity: ProblemShowstopper

I can reproduce the problem with clang/libc++.

A temporary workaround is to

#define ICL_USE_BOOST_MOVE_IMPLEMENTATION

before including ICL headers. This will make it use the boost implementation std::set.

comment:4 by Joachim Faulhaber, 7 years ago

Resolution: fixed
Status: newclosed

Fixed with 1.56.0

Note: See TracTickets for help on using tickets.