繁体   English   中英

这个C ++示例是可移植的吗?

[英]is this C++ example portable?

下面的这个问题,我试图复制粘贴发现的例子在这里在VS2010:

#include <algorithm>
#include <vector>
#include <iostream>

struct S
{
    int number;
    char name;

    S ( int number, char name  )
        : number ( number ), name ( name )
    {}

    // only the number is relevant with this comparison
    bool operator< ( const S& s ) const
    {
        return number < s.number;
    }
};

struct Comp
{
    bool operator() ( const S& s, int i )
    {
        return s.number < i;
    }

    bool operator() ( int i, const S& s )
    {
        return i < s.number;
    }
};

int main()
{
    std::vector<S> vec = { {1,'A'}, {2,'B'}, {2,'C'}, {2,'D'}, {3,'F'}, {4,'G'} }; //this syntax won't compile in VS2010, so you can leave an empty vector here

    auto p = std::equal_range(vec.begin(),vec.end(),2,Comp());

    for ( auto i = p.first; i != p.second; ++i )
        std::cout << i->name << ' ';
}

这将在发布模式下正常编译,但在调试模式下,它将无法编译。 原因是在调试模式下,实现将使用给定的谓词检查迭代器范围是否已经排序:

template<class _FwdIt,
    class _Pr> inline
    void _Debug_order2(_FwdIt _First, _FwdIt _Last, _Pr _Pred,
        _Dbfile_t _File, _Dbline_t _Line, forward_iterator_tag)
    {   // test if range is ordered by predicate, forward iterators
    for (_FwdIt _Next = _First; _First != _Last && ++_Next != _Last; ++_First)
        if (_DEBUG_LT_PRED(_Pred, *_Next, *_First))
            _DEBUG_ERROR2("sequence not ordered", _File, _Line);
    }

这最终要求:

template<class _Pr, class _Ty1, class _Ty2> inline
    bool _Debug_lt_pred(_Pr _Pred,
        const _Ty1& _Left, const _Ty2& _Right,
        _Dbfile_t _File, _Dbline_t _Line)
    {   // test if _Pred(_Left, _Right) and _Pred is strict weak ordering
    if (!_Pred(_Left, _Right))
        return (false);
    else if (_Pred(_Right, _Left))
        _DEBUG_ERROR2("invalid operator<", _File, _Line);
    return (true);
    }

除了在我的情况下,没有operator()可以同时采用左和右“S”参数。 那么,Visual实现中是否存在错误? 或者原始的例子不应该是便携式的? 我想我可以通过提供第三个operator()重载来使它工作,但它似乎应该没有

谢谢

标准中没有任何内容要求比较器可以使用范围内的两个对象进行调用。 这是VS 2010使用的标准库中的一个错误。

以下是所有相关要求(引用C ++ 11):

[lower.bound]§1+ 2:

1 要求: [first,last)的元素e应根据表达式... comp(e, value)进行分区。

2 返回: [first,last]范围内的最远迭代器i ,使得对于[first,i)范围内的任何迭代器j ,以下相应条件成立:... comp(*j, value) != false

[upper.bound]§1+ 2:

1 要求: [first,last)的元素e应根据表达式... !comp(value, e)进行分区。

2 返回:最远迭代i在范围[first,last] ,使得对于任何迭代j范围[first,i)下列相应条件成立:... comp(value, *j) == false

[equal.range]§1+ 2:

1 要求: [first,last)的元素e应根据表达式... comp(e, value)!comp(value, e)进行分区。 此外,对于[first, last)所有元素e ,... comp(e, value)应表示!comp(value, e)

2 返回:

...

 make_pair(lower_bound(first, last, value, comp), upper_bound(first, last, value, comp)) 

(省略号用于非比较器版本)。

Angew已经引用了该标准,并指出VS有缺陷。 我只是想强调VS2010在这里有两个错误 (在调试模式下):

  1. 它尝试使用Compare::operator(_Ty1, _Ty2) ,该标准不需要存在。 这个已知的错误已被Angew强调并由Ben的评论指出。

  2. 它测试输入范围是否已排序,标准也不需要。 这是一个更严重的错误,因为它降低了equal_range的可用性,并且在最坏的情况下需要一个完整的范围,即使这在算法上是不必要的。 也许有人可以向MS提交错误报告?

请注意,第一个错误仅仅是第二个错误的结果(在equal_range的实现中)。 据推测,对于大多数应用程序,输入范围已经排序,部分原因是用户不必要地对其进行排序 (证明MS库中的错误导致错误的用户代码),并且只是提供额外的比较运算符来解决问题(就OP的问题而言) )。

[lib.equal.range]告诉:

要求:类型T是LessThanComparable(20.1.2)。

效果:查找最大的子范围[i,j],使得值可以插入其中的任何迭代器k而不违反排序。 k满足相应的条件:!(* k <value)&&!(value <* k)或comp(* k,value)== false && comp(value,* k)== false。

您的代码满足这两个条件并且编译得很好,这意味着它是visual studio中的一个错误。

作为一般答案。 每个编译器和标准库都会有一些怪癖和地方,它们没有正确实现标准。 这意味着除非代码在不同的平台上进行测试,否则总是有可能需要进行微小的更改。

从好的方面来说,如果一个人试图保持标准,那么这些变化应该非常小。

为了使相同的范围正常工作,范围需要排序,我认为VS编译器试图说你的意图是错的,也许?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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