C++ 为什么可以';我不能用显式模板参数调用模板友元函数吗?
考虑以下示例:C++ 为什么可以';我不能用显式模板参数调用模板友元函数吗?,c++,templates,friend,friend-function,C++,Templates,Friend,Friend Function,考虑以下示例: 结构{ 样板 富友友(S){ } }; int main(){ S S; 富(s);//(1) 富(s);//(2) } 我的GCC 9.2.0未能编译(2),出现以下错误: a.cpp: In function 'int main()': a.cpp:10:5: error: 'foo' was not declared in this scope 10 | foo<void>(s); | ^~~ a.cpp:10:9: erro
结构{
样板
富友友(S){
}
};
int main(){
S S;
富(s);//(1)
富(s);//(2)
}
我的GCC 9.2.0未能编译(2)
,出现以下错误:
a.cpp: In function 'int main()':
a.cpp:10:5: error: 'foo' was not declared in this scope
10 | foo<void>(s);
| ^~~
a.cpp:10:9: error: expected primary-expression before 'void'
10 | foo<void>(s);
| ^~~~
a.cpp:在函数“int main()”中:
a、 cpp:10:5:错误:未在此作用域中声明“foo”
10 |富(s);;
| ^~~
a、 cpp:10:9:错误:应在“void”之前使用主表达式
10 |富(s);;
| ^~~~
但是,
(1)
工作正常。为什么会这样?如何使用显式模板参数调用foo
?它是模板这一事实并不重要。在声明友元函数的位置定义的友元函数只能通过查找找到。当您使用模板参数时,编译器会尝试使用正常的非限定查找来查找名为foo
的函数模板,但失败foo(s)
查找foo
与s
(全局名称空间)相关联的名称空间,并找到您定义的友元函数。Clang能够提供一些信息:
<source>:9:5: warning: use of function template name with no prior declaration in function call with explicit template arguments is a C++20 extension [-Wc++20-extensions]
foo<void>(s);
^
1 warning generated.
如果您试图省略前向声明
(a)
,您会发现您无法将默认模板参数添加到(b)
,因为它是(b)的重新声明,您无法将其添加到(c)
,因此无法引入默认模板参数。类主体中的friend
函数定义不会使friend
函数在封闭的命名空间范围内可见,以进行常规的非限定名称查找(尽管它们被放置在此命名空间范围内)
为了使其可见,您需要在名称空间范围中为模板添加一个声明(无论这是在定义之前还是之后发生):
有趣的我不知道规则变了。:)
struct S;
template<typename T = void>
void foo(S); // (a)
struct S {
template<typename T>
friend void foo(S); // (b)
};
template<typename T>
void foo(S) { // (c)
// Needs S to be complete.
}
int main() {
S s;
foo(s);
foo<void>(s);
}
struct S {
template<typename T = void>
friend void foo(S) {
}
};
template<typename T>
void foo(S);
int main() {
S s;
foo(s); // (1)
foo<void>(s); // (2)
}
struct S {
template <typename T = void>
friend void foo(S) {}
};
template<int>
void foo();
int main() {
S s;
foo(s); // (1)
foo<void>(s); // (2)
}