如果我有一个容器std::vector<T*> items
,我可以创建一个IndirectIterator
,它 Package 了std::vector<T*>::iterator
,并允许在T
而不是T*
上迭代。
我是否可以将iter_swap
专用于IndirectIterator
,以使标准算法(如std::sort
)通过指针交换项?
也就是说,如果我写下面的代码,它会对标准算法产生影响吗?
namespace some_namespace
{
template <typename IterT>
class IndirectIterator
{
IterT m_base;
public:
typedef IterT base_iterator;
typedef /* ... */ reference;
/* ... */
reference operator*() const { **m_base; }
const base_iterator& base() const { return m_base; }
base_iterator& base() { return m_base; }
};
template <typename T>
void iter_swap(IndirectIterator<T>& a, IndirectIterator<T>& b)
{
using std::iter_swap;
iter_swap(a.base(), b.base());
}
}
这种特殊化的好处是它交换指针而不是完整的T示例,因此它更快(潜在地)。
4条答案
按热度按时间eulz3vhy1#
据我所知,
iter_swap
只在std::reverse
中使用,并且它没有提到任何类型的依赖于参数的查找:它总是使用std::iter_swap
,而且因为你不允许重载std
命名空间中的函数,所以你不太走运。cwtwac6a2#
我是否可以将
iter_swap
专用于IndirectIterator
,以使标准算法(如std::sort
)通过指针交换项?你总是可以进行重载/特化,但是你的问题是你是否可以在命名空间
std
内特化iter_swap
。我认为标准中的答案并不明确,我发现在某些情况下,我不得不在
std
中定义一个特殊的iter_swap
,以便std::sort
使用它。在gcc标准库中,std::sort
使用限定的std::iter_swap
。这可能是
std::sort
中的一个缺陷。IMOstd::sort
应该调用一个不合格的swap_iter
。也就是说,如果我写下面的代码,它会对标准算法产生影响吗?
至少在GCC中没有,因为标准算法使用合格的
std::iter_swap
(bug?)我认为标准对此并不清楚。wmomyfyw3#
你可以重新打开
std
命名空间,并在std
中专门化模板,只要你专门化它们为用户定义的类型。在你的情况下,你实际上可以专门化std::iter_swap
为你的目的,只要确保你是在std
命名空间中做的,而不是在你自己的命名空间中(如你的例子)。这不是很优雅,但这是允许的。9gm1akwq4#
从C++20开始,答案是明确的“是的,你 * 可以 * 定制你自己的ADL
iter_swap
”。STL算法 * 应该 * 使用它,但不是必须的,而且在实践中存在实现分歧。为了定制一个定制点,你应该使用“隐藏朋友习惯用法”:
这里有细微的变化:你的
iter_swap
已经通过可变引用获取了它的参数!这是不起作用的,例如,如果它被传递了一个常量IndirectIterator
,或者一个右值IndirectIterator
。迭代器参数应该总是通过值来获取。同样,提供一个非常量版本的base()
是没有意义的。你的base()
是一个getter,而不是setter;由于X1 M5 N1 X是常数成员函数的相同原因,它应该是常数成员函数。最后,这里最大的警告是,你绝不能定制
iter_swap
来做任何 * 明显不同于 * 交换迭代器目标的事情。如果你这样做了,那么它就是未定义的行为--所有的赌注都是无效的--程序可以做任何事情。正式地说,这个要求在[iterator.cust.swap]中给出:如果重载解决方案选择的[
iter_swap
]函数不交换 E1 和 E2 表示的值,则程序是病态的,不需要诊断。我相信让
iter_swap
交换“第一级”目标而不是“第二级”目标的想法是完全正确的,只要你永远不会依赖于观察差异。标准库仍然 * 被允许 * 绕过iter_swap
,如果它喜欢的话,只做swap(*it, *kt)
;你的代码必须能够科普这个问题,否则“程序是病态的,不需要诊断”(也就是说,你必须完全相信交换这些第一级目标等同于“交换 E1 和 E2 的值”,因此可以与任何其他交换值的方法互换。你不能“依赖"你自己的方法被使用)。Here is a complete C++20 example on Godbolt.截至2023年2月,我在这里看到定制的
iter_swap
实际上正在使用:| 算法|库标准数据库++|libc++|微软|
| - ------|- ------|- ------|- ------|
|
std::ranges::partition
|是的|是的|是的||
std::ranges::sort
|没有|没有|是的||
std::partition
|没有|没有|没有||
std::sort
|没有|没有|没有|