迭代器和无符号整数的重载 + 运算符
Overloading + operator for iterators and unsigned integers
我正在尝试为列表迭代器和无符号整数重载+
运算符(用于练习(。下面的代码似乎工作正常。解释它应该做什么:如果iter
是一个迭代器并且k
一个无符号整数,那么iter+k
(或operator+(iter, k)
(返回一个从递增iter
k次中获得的迭代器。
list<int>::iterator operator+(list<int>::iterator iter, unsigned k)
{
while (k != 0)
{
++iter;
--k;
}
return iter;
}
但是,当我这样模板化时:
template<typename T>
typename list<T>::iterator
operator+(typename list<T>::iterator iter, unsigned k)
{
while (k != 0)
{
++iter;
--k;
}
return iter;
}
并运行一些简单的东西,例如
int main(){
list<int> l{1,2};
list<int>::iterator q = l.begin();
q+1;
}
我收到一个无法破译的大错误。我也尝试无济于事:
int main(){
list<int> l{1,2};
list<int>::iterator q = l.begin();
operator+<int>(q,1);
}
关于为什么会发生这种情况以及如何解决它的任何想法将不胜感激!
问题是模板类型参数T
处于非推导上下文中,无法推导。要使其可推导,您可以这样做:
template<typename T>
T operator+(T iter, unsigned k)
{ ... }
请注意,这种过载可能会造成很大的伤害,因为T
不限于std::list<T>::iterator
。SFINAE可以帮助:
template<typename T, typename = std::enable_if_t<
std::is_same_v<T, typename std::list<
typename std::iterator_traits<T>::value_type>::iterator>>>
T operator+(T iter, unsigned k)
{ ... }
加法。
operator+<int>(q, 1);
失败的原因更微妙。首先,引用标准,[temp.arg.explicit]/8(另见那里的例子(:
但是,当使用具有显式模板参数的函数模板时,调用没有正确的语法形式,除非在调用点存在具有该名称的函数模板。如果没有可见的此类名称,则调用的语法格式不正确,并且依赖于参数的查找不适用。如果某些此类名称可见,则应用依赖于参数的查找,并且可以在其他命名空间中找到其他函数模板。
我们这里有这样一个函数模板,它是我们的operator+
.因此,ADL试图在std::
中找到operator+<int>
。但是,当使用<int>
实例化某些operator+
模板时,编译将失败。哪一个以及如何失败取决于特定的 std 库实现。
例如,gcc 8.1 尝试实例化
template<class _Iterator> constexpr
std::move_iterator<_IteratorL> std::operator+(
typename std::move_iterator<_IteratorL>::difference_type,
const std::move_iterator<_IteratorL>&)
[with _Iterator = int]
并在内部的某个地方失败
error: no type named 'reference' in 'struct std::iterator_traits<int>'
...
如果我们禁用 ADL,它将按预期工作:
::operator+<int>(q, 1);
或
(operator+<int>)(q, 1);
这与模板类型推导C++工作方式有关。由于语言的设置方式,编译器无法推断出 T 应该在list<T>::iterator
的上下文中自动推断出什么。原因是,由于模板专用化,理论上两个不同的list
实例化可能具有相同的嵌套iterator
类型(例如,list<Pizwkat>
和list<Swibble>
(,在这种情况下,编译器将无法确定 T 应该Pizkwat
还是Swibble
,因为这两个选项都可能有效。
我不相信有一个简单的解决方案来解决"添加一个仅适用于列表迭代器的operator +
"的一般问题,尽管您可以考虑使用std::next
和std::advance
函数,它们适用于所有类型的迭代器。(请注意,为库类型添加自定义重载通常不是一个好主意,因此即使您可以执行此操作,它也可能不是您尝试解决的任何问题的最佳解决方案。
- 使用C++中的模板和运算符重载执行矩阵运算
- 为什么这个运算符<重载函数对 STL 算法不可见?
- <T> 通过模板化运算符重载将 std::complex 乘以双倍
- C++20概念:需要运算符重载
- 使用赋值运算符重载从类中返回jobject
- 在运算符重载定义中使用成员函数(const错误)
- 字节到位运算符重载C++
- 为什么在运算符重载时需要参考?
- 类中 c++ 的运算符 + 重载
- 算术复合运算符重载为非成员
- 运算符重载 (+),用于添加两个具有 C++ 的数组
- 交换运算符 + 重载会导致无限递归
- 如何理解新的运算符重载?
- 向量保持复数的运算符重载
- 如何创建运算符重载?
- 链接列表运算符重载没有打印出我想要的内容
- C++:需要帮助了解运算符重载错误
- 使用模板化运算符重载 XOR 运算符失败
- 如何确保接受的C++模板类型使运算符重载?
- 运算符重载使用运算符+添加类模板