【问题标题】:Boost ICL, cardinality of an interval setBoost ICL,区间集的基数
【发布时间】:2014-12-01 09:05:50
【问题描述】:

在 Boost ICL 中,当我在区间集上调用 cardinality() 或 size() 函数时,返回类型为 size_t,与区间类型无关。在 32 位机器上,这是一个 32 位无符号整数。但是,如果我的区间是 int64_t 类型,则基数很容易溢出 32 位整数。我在这里遗漏了一些明显的东西还是这个库的严重缺陷?

编辑:添加示例

以下代码在 64 位机器上编译和运行没有错误,但在 32 位机器上则不会,它会抛出断言。

#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);
}

编辑:我在 Ubuntu 13.10 上使用 boost::icl 版本 1.49.0

编辑:

这并不是 32/64 位的问题,因为以下代码也不适用于 64 位

#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);
}

【问题讨论】:

    标签: c++ boost boost-icl


    【解决方案1】:

    在 Ubuntu 14.04.1 LTS 上使用 Boost 1_54 复制

    这确实似乎是一个错误。要修复的专业是

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

    icl/type_traits/size_type_of.hpp。不知何故,这些天 ICL 开发人员似乎没有使用 -m32 进行测试。

    我已经成功地将它替换为

    // 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
    

    遗憾的是,该 trait 对 SFINAE 不是很友好,因此可以将第一个 bool 模板参数用于 SFINAE。改进可能是:

    • 仅使用 boost 类型特征
    • 使用 Boost Integer 中的整数值扣除,而不是 common_type&lt;...&gt; 用于整数类型

    我已经在 DoTheRightThing(TM) 上测试了 interval_set&lt;double&gt; 以及 g++ -m32 和 -m64 上的 interval_set&lt;uint64_t&gt;


    我会在邮件列表中报告这个。

    【讨论】:

    • 干得好。我发现 get get_size_type 对 SFINAE 不是特别友好,但如果您想将我的 Proof-Of-Concept 补丁作为“想法”添加到问题中,欢迎您。
    • 顺便说一句,这并不是一个 32 位/64 位问题,因为如果您的间隔类型是双倍的,即使在 64 位机器上也会遇到同样的问题。一方面是因为溢出(double range 大于 64 位整数范围),另一方面是因为在这种情况下基数可以是浮点数。他们只需要使用与区间中包含的基数相同的类型。
    • @Konstantin 不要忘记你可以有 UDT(非整数或非算术)类型的区间。最好把这个决定留给图书馆设计师。同时,我更新了我的帖子:)
    • 好吧,但是我可以有 boost::icl::interval_set ,不是吗?或者对于整数数据类型,interval_set 是否明确存在?
    • 对不起,你是对的!这听起来不应该是抱怨:) 我想我只是尴尬地在我使用了将近一年的代码中找到了这个东西。现在我必须重做我的计算。不能靠boost,靠什么!? :)
    猜你喜欢
    • 2015-06-20
    • 2016-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多