c++模板的行为和操作符重载

Behavior of C++ templates and operator overloading

本文关键字:操作符 重载 c++      更新时间:2023-10-16

我想了解下面的代码行为

#define USE_FRIEND 
class Foo
{
public:
    template <typename T>
    Foo& operator<< (T val)
    {
        std::cout << "Inside Foo" << std::endl;
        return *this;
    }
};
class A
{
public:
#ifdef USE_FRIEND
    friend Foo& operator<<(Foo& f, A& a)
    {
        std::cout << "Inside A" << std::endl;
        return f;
    }
#endif
};
int main()
{
    A a;
    Foo f;
#ifdef USE_FRIEND
    std::cout << " using Friend :: ";
#else
    std::cout << " not using Friend :: ";
#endif
    f << a;
    system("pause");
    return 0;
}

上述代码两次执行的输出,一次带有Using友元,另一次没有:

案例1:

using Friend :: Inside A

案例2:

not using Friend :: Inside Foo

我能理解第二种情况,但有人能解释第一种情况吗

重载解析是一件复杂的事情,但这里有两个相关的规则:

  • 可行的重载如下:

    1. template <typename T> Foo & Foo::operator<<(T)

    2. Foo & operator<<(Foo &, A &)

  • 当调用operator<<(f, a)时,则两个重载匹配,并且它们都在鼻子上匹配,从而导出模板中的T = A在精确性上没有差别,因为引用被视为"完美匹配"。

  • 因此这两个重载是绑定的,并且分辨率看起来是不明确的。然而,有一个决定性因素:第1条是模板,而第2条不是。在这种情况下,非模板是更好的匹配