简体   繁体   中英

Boost ICL, cardinality of an interval set

In Boost ICL, when I call cardinality() or size() functions on an interval set, the return type is size_t, independent of the type of interval. On 32-bit machines this is a 32-bit unsigned integer. If my intervals, however, are of type int64_t, the cardinality can easily overflow the 32-bit integer. Am I missing something obvious here or is this a serious flaw of this library?

EDIT: example added

The following code compiles and runs without error on 64-bit but not on 32-bit machines, where it throws the assertion.

#include <boost/icl/interval_set.hpp>

int main()
{
    boost::icl::interval_set<int64_t> is;
    is.add(boost::icl::interval<int64_t>::closed(1, 4294967297LL));
    assert(boost::icl::cardinality(is) == 4294967297LL);
}

EDIT: I'm using boost::icl version 1.49.0 on Ubuntu 13.10

EDIT:

This is not particularly a 32/64-bit problem, as the following code wouldn't work on 64-bit either

#include <boost/icl/interval_set.hpp>
int main()
{
    boost::icl::interval_set<double> is;
    is.add(boost::icl::interval<double>::closed(1, 1.5));
    assert(boost::icl::cardinality(is) == 0.5);
}

Reproduced with Boost 1_54 on Ubuntu 14.04.1 LTS

This indeed seems to be a bug. The specialization to fix is

template <class Type> 
struct get_size_type<Type, false, false, false>
{ 
    typedef std::size_t type; 
};

In icl/type_traits/size_type_of.hpp . Somehow the ICL devs appear not to be testing with -m32 these days.

I've had success replacing it by

// BEGIN SEHE WAS HERE
template <class Type> 
struct get_size_type<Type, std::enable_if<not boost::is_arithmetic<Type>::value, mpl::false_>::type::value, false, false>
{ 
    typedef std::size_t type; 
};

template <class Type> 
struct get_size_type<Type, std::enable_if<boost::is_arithmetic<Type>::value, mpl::false_>::type::value, false, false>
{ 
    typedef typename std::common_type<Type, std::size_t>::type type; 
};
// END SEHE WAS HERE

The trait is sadly not very SFINAE friendly, hence the hack to use the first bool template argument for SFINAE. Improvements could be:

  • use boost type traits only
  • use integral value deduction from Boost Integer as opposed to common_type<...> for integral types

I've tested this to DoTheRightThing(TM) for interval_set<double> as well as interval_set<uint64_t> on g++ -m32 and -m64.


I'd report this on the mailing list.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM