c++ - std::set 插入器不尊重自定义比较器。(可能的编译器错误?)
问题描述
我发现std::inserter
on anstd::map<T, C>
并不总是尊重自定义比较器,而是有时会退回到默认值operator<
/ std::less
。有没有人知道为什么会这样?考虑到零星的性质,我觉得这可能是一个编译器错误。特别是,我有这样的功能:
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;
}
但这并不总是使用我的自定义C
比较器,有时(我知道,我也希望我能找到一个模式)会std::less
改为使用。如果我用 maunal 构造替换它,则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;
}
我觉得这可能是一个编译器错误(gcc 版本 7.3.0),因为http://en.cppreference.com/w/cpp/iterator/inserter上提供的参考资料描述inserter
为简单地委托给insert_iterator
:
template< class Container >
std::insert_iterator<Container> inserter( Container& c, typename Container::iterator i )
{
return std::insert_iterator<Container>(c, i);
}
此外,官方 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);
这显然不会在这里发生,因为返回insert_iterator
的是 type 类std::set<T, C = std::less<T>>
,而不是std::set<T, C>
.
除了编译器错误之外,还有对此的解释吗?
解决方案
“可能的编译器错误”之于 C++ 就像“它可能是狼疮”之于 House MD。
话虽如此,在Documentation之后,您似乎正在使用该函数的版本1),其中明确指出:
1) 使用 operator< 比较元素,并且范围必须相对于相同进行排序。
您应该做的是将您的比较器传递给std::set_union
,根据该函数的版本3)。
所以真正的谜团是:为什么有时会使用您的比较器。但是,由于您不尊重函数的先决条件:
范围必须相对于相同进行排序。
然后没有定义预期的行为,所以行为不是“不正确的”。
推荐阅读
- javascript - 联系表格 7 自定义占位符文本
- unix - 替换所有逗号,除了两个等号之间的最后一个逗号
- asp.net - IIS并发处理请求慢
- r - 当最后一个值为零时如何修剪向量
- spring - 无法使用 KafkaTemplate 从 Kafka 发送消息
- sql - MS SQL - 从特定模式或所有模式中的所有视图中查找所有表别名
- reactjs - 使用 React 和 axios 调用 Deezer API 失败
- php - 在 PHP 中创建搜索函数
- vba - Vba如何修改代码以在过滤后自动选择所有行
- python-2.7 - 使用 ruamel CommentedMap() 手动添加项目