c++ - 在 Clang 和 libc++ 中使用反向 vector 迭代器时,“重载运算符的使用不明确”

标签 c++ clang libc++

据我了解 C++ ADL,此编译错误是合法的。 但同时我不明白为什么这种失败只发生在 clang + libc++ 配置上,并且只发生在我们使用反向迭代器时。法线 vector 迭代器不会导致这种情况。

#include <vector>
#include <iostream>

namespace NS1
{
struct Foo
{
    explicit Foo(const int i): m_i(i)
    {}
    bool operator==(const Foo& that) const
    {
        return this->m_i == that.m_i;
    }

    int m_i;
};

template <typename T>
bool operator!=(const T& a, const T& b)
{
    return !(a == b);
}
}

int main(void)
{
    std::vector<NS1::Foo> n;
    // error: use of overloaded operator '!=' is ambiguous (with operand types 'std::__1::reverse_iterator
    for(auto it = n.rbegin(); it != n.rend(); ++it)
    {
        std::cout<<it->m_i;
    }
}

错误是:

error: use of overloaded operator '!=' is ambiguous (with operand types 'std::__1::reverse_iterator<std::__1::__wrap_iter<NS1::Foo *>>' and 'std::__1::vector<NS1::Foo, std::__1::allocator<NS1::Foo>>::reverse_iterator' (aka 'reverse_iterator<__wrap_iter<NS1::Foo *>>'))
for(auto it = n.rbegin(); it != n.rend(); ++it)
                          ~~ ^  ~~~~~~~~

有谁知道是否可以使 clang + libc++ 配置的行为与其他配置(gcc、msvc)一样?

这是一个关于 godbolt 的小例子:https://godbolt.org/z/8cKPY6

最佳答案

As far as I understand C++ ADL this compilation error is legit. But at the same time I dont understand why this failure happens only on clang + libc++ configuration, and only when we use reverse iterators. Normal vector iterators dont lead to this

好吧,如果检查错误消息,就会发现操作数的实际类型是此类型的某种变体

std::__1::reverse_iterator<std::__1::__wrap_iter<NS1::Foo *>>

它是一些模板的实例,用于生成反向迭代器。由于您了解 ADL,因此您知道当操作数是类模板特化时,关联的命名空间集也由模板参数的命名空间组成。这就是您考虑 NS1::operator!= 的原因。由于它是一个不受约束的函数模板,因此它可能是重载解析的可行候选者。因此发生了冲突。

原因是前向迭代器不会发生这种情况,这可能取决于其实现细节。他们可以

  1. 不是某些模板本身的特化。即 vector 特化的常规嵌套类。 vector 的关联命名空间不会保留。
  2. 根本就不是上课。 vector 的迭代器可以实现为 vector 缓冲区的简单指针。

我会认真地重新审视您对这样一个不受约束的操作符!=的需求。这将是一种非常简单的解决问题的方法。

关于c++ - 在 Clang 和 libc++ 中使用反向 vector 迭代器时,“重载运算符的使用不明确”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65461276/

相关文章:

c++ - 如何在 Release模式下调试?

c - 如何禁用 clang 的 gnu 扩展?

c++ - 用户泄漏、libc++ 泄漏或误报

android - 在 Android 5.0 (Lollipop) 上运行时使用 APP_STL=c++_shared 在 sscanf 中挂起

c++ - 如何实现两个第三方类型之间的转换?

c++ - 使用 cv_image 实现 dlib pyramid_up

objective-c - 不确定如何导出 Objective-C 类。架构 i386 的 undefined symbol

Clang 无法编译 c11 程序,引用 "implicit declaration is illegal in c99"

c++ - std::stringstream 的默认 `fill character` 是什么?

c++ - C++ 11 auto关键字多少太多了?