c++ - ADL 应该如何发挥作用?

标签 c++ clang argument-dependent-lookup


最近,我遇到了 clang++ 5.0.0 编译器的一个问题,通过 ADL,它无法在 Mac 上获取正确的函数(但 g++ 在 Linux 上正确地执行了)。我想知道这是否是编译器问题或总体上糟糕的类设计。
这是示例代码(纯粹用于说明目的):

namespace test {
    class Ops {
      public:
        Ops():val_(0){}
        template<typename T>
        Ops& operator<< (const T& val) {
            std::cout << "Called member function" << std::endl;
            this->val_ = val;
            return *this;
        }
      private:
        int val_;
    };

    template<typename T>
    struct Any {
        T val_;
    };

    template <template<typename> class E,  typename T>
    Ops& operator<< (Ops& op, const E<T>& val) {
        std::cout << "Global function" << std::endl;
        return op;
    }
}

int main() {
    test::Ops op;
    int k = 9;
    test::Any<int> a;
    op << a;

    return 0;
}

我想知道 ADL 和模板参数推导如何逐步找到最佳匹配?
是否存在同一个“主体”会优先选择成员(member)功能而不是自由功能的情况? (这就是产品构建中发生的情况)

提前致谢。

最佳答案

这是详细发生的事情,也是每个编译器应该做的:通过限定查找找到候选模板函数

template <typename T>
test::Ops::operator<<(const T&)

而第二个候选是通过 ADL 使用模板参数推导(cfr. temp.deduct.conv)生成的

template <template <typename> class E, typename T>
test::operator<<(test::Ops&, const E<T>&)

此后,重载决议启动(参见 13.3.3),并且非成员 (F1) 优先于成员 (F2),因为

  • F1 and F2 are function template specializations, and the function template for F1 is more specialized than the template for F2 according to the partial ordering rules described in 14.5.6.2.

因此选择作为要调用的函数。

回答你的问题:这取决于重载解析规则。作为成员函数或在内部作用域中不会影响结果,例如

namespace test {
    class Ops {
      public:
        Ops():val_(0){}

        template<typename T>
        Ops& operator<< (const T& val) {
            std::cout << "Called member function" << std::endl;
            this->val_ = val;
            return *this;
        }

      private:
        int val_;
    };

    template<typename T>
    struct Any {
        T val_;
    };

    template <typename E>
    Ops& operator<< (Ops& op, const E& val) {
        std::cout << "Global function" << std::endl;
        return op;
    }
}

只会触发重载解析错误'use of overloaded operator '<<' is ambiguous '.

作为一个优点:即使选择了成员函数,它也是错误的:this->val被分配了一个非整数类型。

关于c++ - ADL 应该如何发挥作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26000553/

相关文章:

c++ - std::optional 是否更改函数的签名?

c++ - Simple Spirit X3 分词器无法编译,属性不匹配

c++ - 奇怪的 C++ 链接错误

android - 使用 Android NDK 使用 clang++ 编译 C++ 代码时未定义对 `_Unwind_Resume' 的引用

c++ - 参数相关查找未按预期工作

c++ - 对参数依赖查找和友元函数定义的混淆

c++ - 为什么 C++11 不支持这样的名称查找?

c++ - QImage::setPixel: 坐标超出范围

c++ - 代码未添加最后一个默认值

c++ - 为什么尽管使用了 -isystem,但 clang 在我的标题上报告了警告,而 gcc 没有报告?