gpt4 book ai didi

c++ - 为什么好友成员函数没有自动识别为函数模板?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:30:48 26 4
gpt4 key购买 nike

C++ 常见问题解答 35.16

http://www.parashift.com/c++-faq-lite/template-friends.html

#include <iostream>

template<typename T>
class Foo {
public:
Foo(T const& value = T());
friend Foo<T> operator+ (const Foo<T>& lhs, const Foo<T>& rhs);
friend std::ostream& operator<< (std::ostream& o, const Foo<T>& x);
private:
T value_;
};

车主声称:

'当编译器看到 friend 在类定义中正确排列时,就会发生问题。那时它还不知道友元函数本身就是模板(为什么?类模板成员函数默认不是函数模板吗?);它假设它们不是像这样的模板:'

Foo<int> operator+ (const Foo<int>& lhs, const Foo<int>& rhs)
{ ... }

std::ostream& operator<< (std::ostream& o, const Foo<int>& x)
{ ... }

为什么以上都是非模板?这些模板不是通过int实例化的吗?

'当您调用 operator+ 或 operator<< 函数时,此假设会导致编译器生成对非模板函数的调用,但链接器会给您一个“未定义的外部”错误,因为您实际上从未定义过那些非模板函数- 模板功能。 '

事实上,为了使编译器将上面的内容识别为函数模板,程序员必须像下面这样显式地执行此操作:

template<typename T> class Foo;  // pre-declare the template class itself
template<typename T> Foo<T> operator+ (const Foo<T>& lhs, const Foo<T>& rhs);
template<typename T> std::ostream& operator<< (std::ostream& o, const Foo<T>& x);

谁能解释一下?我觉得这很烦人,不知道为什么编译器不通过用“int”替换 T 来实例化 Foo 类的实例,然后就此结束。

谢谢。

最佳答案

类模板的成员函数是模板的一部分,因此用模板实例化,但友元不是。考虑非模板情况:

struct S {
friend void foo(S);
};

请注意 void foo(S)此时不必声明; friend声明是说如果一个函数void foo(S)定义,那么该函数将可以访问S .它可能永远不会真正被定义,这很好。

使用模板,情况是一样的:

template<typename T> struct S {
friend void foo(S);
};

这是说对于任何类型 T , 如果一个函数 void foo(S<T>)被定义 那么该函数可以访问 S<T> .通过重载,该函数应该是一个具体的函数:

void foo(S<char>) { }
void foo(S<int>) { }

编译器不知道您打算稍后提供一个可用于所有T 的函数模板。 .相反,如果已经声明了适当的函数模板,那么如果您通过添加尖括号指定它应该被实例化,它将被实例化。

至于为什么必须前向声明模板,"template"没有理由必须只有一个声明。考虑:

#include <iostream>
template<typename T> struct S;
template<typename T> void foo(S<T>);
template<typename T> void foo(S<T *>);
template<typename T> struct S {
friend void foo<>(S);
};
template<typename T> void foo(S<T>) { std::cout << "template template friend\n"; }
template<typename T> void foo(S<T *>) { std::cout << "template specialization template friend\n"; }
template void foo(S<void *>);
int main() {
foo(S<int>());
foo(S<void *>());
}

这里有两个特化 foo ,并且它们都必须提前声明,以便 friend可以在它们之间进行选择。

关于c++ - 为什么好友成员函数没有自动识别为函数模板?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11864102/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com