简体   繁体   English

std :: set插入程序不符合自定义比较器。 (可能的编译器错误?)

[英]std::set inserter not respecting custom comparator. (possible compiler bug?)

I'm finding that std::inserter on an std::map<T, C> does not always respect the custom comparator, but rather will sometimes fall back to the default operator< / std::less . 我发现std::map<T, C>上的std::inserter并不总是尊重自定义比较器,而是有时会退回到默认operator< / std::less Does anyone have any experience with why this may be? 有人对此有任何经验吗? I feel like it could be a compiler bug, given the sporadic nature. 考虑到零星的本性,我觉得这可能是编译器错误。 In particular, I have a function like so: 特别是,我有一个像这样的功能:

template <typename T, typename C>
std::set<T, C> operator|(const std::set<T, C> &lhs, const std::set<T, C> &rhs)
{
  std::set<T, C> out;
  std::set_union(lhs.begin(), lhs.end(),
                 rhs.begin(), rhs.end(),
                 inserter(out, out.end()));
  return out;
}

But this does not always use my custom C comparator, and sometimes (I know, I too wish I could find a pattern) will just use std::less instead. 但这并不总是使用我的自定义C比较器,有时(我知道,我也希望我能找到一种模式)只会使用std::less来代替。 If I replace it with a maunal construction of the std::insert_iterator<std::set<T, C>> , everything works correctly: 如果我将其替换为std::insert_iterator<std::set<T, C>>的主要构造,则一切正常:

template <typename T, typename C>
std::set<T, C> operator|(const std::set<T, C> &lhs, const std::set<T, C> &rhs)
{
  std::set<T, C> out;
  std::set_union(lhs.begin(), lhs.end(),
                 rhs.begin(), rhs.end(),
                 std::insert_iterator<std::set<T, C>>(out, out.end()));
  return out;
}

I feel like this could be a compiler bug (gcc version 7.3.0) because the reference available on http://en.cppreference.com/w/cpp/iterator/inserter describes inserter to simply delegate to insert_iterator : 我觉得这可能是编译器错误(gcc版本7.3.0),因为http://en.cppreference.com/w/cpp/iterator/inserter上提供的参考描述了仅将委托委托给insert_iterator inserter insert_iterator

template< class Container >
std::insert_iterator<Container> inserter( Container& c, typename Container::iterator i )
{
    return std::insert_iterator<Container>(c, i);
}

Furthermore, the official C++ standard, section 24.5.2.5 (accessed via http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf , page 859) puts the definition of inserter as returning an insert iterator of the same type as is passed in the first argument: 此外,官方的C ++标准第24.5.2.5节(可通过http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf ,第859页访问)提出了插入程序的定义返回与第一个参数中传递的类型相同的插入迭代器:

template <class Container>
      insert_iterator<Container> inserter(Container& x, typename Container::iterator i);

Which clearly isn't happening here, as the returned insert_iterator is for a class of type std::set<T, C = std::less<T>> , not std::set<T, C> . 显然这里没有发生,因为返回的insert_iterator用于std::set<T, C = std::less<T>> ,而不是std::set<T, C>

Is there an explanation for this besides compiler bug? 除了编译器错误,是否还有其他解释?

"possible compiler bug" is to C++ what "It might be Lupus" is to House MD. 对于C ++,“可能的编译器错误”对House MD而言是“可能是狼疮”。

That being said, following the Documentation , you appear to be using version 1) of the function, which clearly states: 就是说,在Documentation之后 ,您似乎正在使用该功能的版本1) ,该版本明确指出:

1) Elements are compared using operator< and the ranges must be sorted with respect to the same. 1)使用operator <比较元素,并且必须对范围进行排序。

What you should be doing, is pass your comparator to std::set_union , as per version 3) of the function. 您应该做的是,按照函数的版本3)将比较器传递给std::set_union

So the real mystery is: why is your comparator used at all sometimes. 因此,真正的奥秘在于:为什么有时总是使用您的比较器。 However, since you do not respect the preconditions of the function: 但是,由于您不遵守该功能的前提条件:

the ranges must be sorted with respect to the same. 范围必须相对于相同进行排序。

Then there is no expected behavior defined, so the behavior is not "incorrect". 然后,没有定义预期的行为,因此该行为不是“不正确的”。

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

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