GCC中优先队列的奇怪的shared_ptr比较器选择

时间:2018-07-13 19:07:50

标签: c++ c++11 gcc stl clang

我有一个用std::shared_ptr包装的类,我想在std::priority_queue的帮助下选择前k个对象。因此,我定义了operator <,并希望一切都会好起来的。但这不是真的。默认情况下(带有gcc)std::priority_queuestd::shared_ptr使用默认比较器,它比较地址。

但是,如果我对std :: vector使用std :: sort且未指定比较器,则行为会有所不同,我的operator <将被使用。这有点出乎意料且行为不一致。

代码示例:

struct document
{   
    float rank;
    document(float rank):
        rank(rank)
    { }
};

using doc_ptr = shared_ptr<document>;

bool operator < (const doc_ptr& x, const doc_ptr& y)
{   
    return x->rank < y->rank;
}

int main()
{
    priority_queue<doc_ptr> pq;
    for(int i = 0; i < 10; i++) {
        float r = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);
        pq.push(make_shared<document>(r));
    }

    vector<doc_ptr> pq_v;

    while(!pq.empty()) {
        cout << pq.top()->rank << " " << uint64_t(pq.top().get()) << endl;
        pq.pop();
    }

    return 0;
}

我得到以下输出:

0.277775 35463848
0.76823 35463800
0.335223 35463752
0.197551 35463704
0.55397 35463560
0.911647 35463512
0.783099 35463384
0.79844 35463336
0.394383 35463288
0.840188 35463208

使用clang(Apple LLVM版本9.1.0(clang-902.0.39.2)),一切正常。

std::priority_queue中包含std::sortstd::vector的完整代码:https://ideone.com/awsdrO

我想这可能与名称解析有关,但我自己找不到。所以,我想知道谁在这里,为什么?

UPD :这里更简单的示例:https://ideone.com/wm1YBw 输出的最后一行在gcc和clang中有所不同,因为gcc为std::less提供了shared_ptr的专门化,但是clang没有。

1 个答案:

答案 0 :(得分:0)

事实证明,gcc为std::less提供了std::shared_ptr的专业化,不应提供。您可以在this错误报告中找到所有其他详细信息。

如果我正确理解:C ++标准的早期草案已明确提及,则应为std::less提供std::shared_ptr的专业化。在工作过程中,此提及已从标准中删除,但在gcc代码本身中并未删除。

因此,如果您使用的是未修复的gcc版本,请小心。