模板参数阴影与朋友

Template parameter shadows with friend?

本文关键字:朋友 阴影 参数      更新时间:2023-10-16

在下面的例子中,重载<< operator

#include <iostream>
template <typename T>
class MyClass {
    public:
        MyClass(T X, T Y):x(X), y(Y) {}
        template <typename U>
        friend std::ostream& operator <<(std::ostream &os, const MyClass<U> &cl);
    private:
        T x;
        T y;
};
template <typename T>
std::ostream& operator <<(std::ostream &os, const MyClass<T> &cl)
{
    os << cl.x << " " << cl.y;
    return os;
}
int main()
{
    MyClass<int> cl(1, 2);
    std::cout << cl << std::endl;
}

我已经搜索了其他问题,但我找不到为什么我需要:

template <typename U>
friend std::ostream& operator <<(std::ostream &os, const MyClass<U> &cl);

U而不是T typename?因为最终UT都是ints.

你不能再次使用template <typename T>,因为在行的其余部分,它不知道你的意思是两个T中的哪一个。有点像这样,这也是一个错误:

void foo(int x) {
  int x = 4;
  cout << x;  // which x?
}

编译器不够聪明,无法弄清楚在这种情况下,您将始终希望两个T相同,就像上面foo函数中的错误不会消失一样,如果您只在程序中调用foo(4)

但是您在这里意识到的是,您实际上根本不需要模板参数来operator<<!那是因为在这种情况下,您确切地知道要使用哪种类型,whch 是MyClass<T> .通常,当您知道所需的确切类型时,您可以摆脱模板参数。这称为显式专用化,通常如下所示:

template <>
friend std::ostream& operator<< <T>(std::ostream& os, const MyClass<T> &cl);

请注意空模板参数列表 template <> ,上面写着"我不需要模板参数",然后是函数名称后面的<T>,上面写着"因为我希望模板参数类型完全T",其中TMyClass模板的特定实例中已经知道。但是,这在这里不起作用,因为C++语言规范中只有一条规则,即friend声明中不允许显式专用化。(我不确定这条规则背后的理由是什么,但这是一个规则。

因此,

由于您不能重用标识符T,并且不能显式专用化,因此剩下的唯一选择是对模板参数使用其他标识符,例如 U