这是这个问题的后续行动。最初的案例是另一回事,但在我写了一个糟糕的答案和OP澄清的过程中,我们可能需要一个语言律师的帮助来理解正在发生的事情。
在C++中的思考-实用编程第2卷-您可以找到以下示例( Thinking,online 这里):
//: C05:FriendScope3.cpp {-bor} // Microsoft:使用-Za (与ANSI兼容的)选项#包括使用命名空间std;模板类友好{T t;public: Friendly(const T& theT):t(theT) {} friend void f(const Friend&fo){ cout << fo.t << endl;}<< g() { f(*this);} };void h() {f(友好(1));} int main() { h();友好(2).g();}/:~
他们继续解释(强调我的):
这与前面的示例有一个重要的区别:f不是这里的模板,而是一个普通的函数。(请记住,在暗示f( )是一个模板之前,尖括号是必需的。)每次实例化友好类模板时,都会创建一个新的普通函数重载,它接受当前友好专门化的参数。这就是丹·萨克斯所谓的结交新朋友。68这是为模板定义朋友函数的最方便的方法。
到目前一切尚好。令人费解的部分是"f不是这里的模板,而是一个普通函数“+每次实例化友好类模板时,就会创建一个新的普通函数重载”,当您考虑这个示例时:
template <typename T>
struct foo {
friend void bar(foo x){
x = "123";
}
};
int main() {
foo<int> x;
bar(x);
}实例化foo<int>不会导致编译器错误!只调用bar(x)原因(gcc 10.2):
<source>: In instantiation of 'void bar(foo<int>)':
<source>:10:10: required from here
<source>:4:11: error: no match for 'operator=' (operand types are 'foo<int>' and 'const char [4]')
4 | x = "123";
| ~~^~~~~~~
<source>:2:8: note: candidate: 'constexpr foo<int>& foo<int>::operator=(const foo<int>&)'
2 | struct foo {
| ^~~
<source>:2:8: note: no known conversion for argument 1 from 'const char [4]' to 'const foo<int>&'
<source>:2:8: note: candidate: 'constexpr foo<int>& foo<int>::operator=(foo<int>&&)'
<source>:2:8: note: no known conversion for argument 1 from 'const char [4]' to 'foo<int>&&'普通函数的实例化?只有当函数被调用时才会失败?这里发生什么事情?
bar真的是一个普通的函数吗?它只在调用时被实例化?为什么,当它是一个普通的功能?当bar被实例化时,foo<int>实际上发生了什么(作者称之为“创建了一个新的、普通的函数重载”,不确定这意味着什么)?
对不起,太多了,太让人费解了。请不要错过language-lawyer标签,我想知道为什么/标准的哪些部分是这样的,而不仅仅是什么。
PS:为了确保我再次检查了一下,当bar未被调用时,三个常见的嫌疑人都编译了这个示例,没有什么大的抱怨:https://godbolt.org/z/Wcsbc5qjv。
发布于 2021-04-29 02:42:36
. class /2类模板专门化的隐式实例化导致声明的隐式实例化,而不是类的定义、默认参数或no以外-说明符的隐式实例化.朋友..。 tem.inst/4.如果函数的声明是从朋友函数定义中实例化的,则在需要函数定义才能存在的上下文中引用该函数时,将隐式实例化.
发布于 2021-04-29 04:11:13
像这样的构造是模板的一部分,而不是模板本身,它们被称为模板化的,因为它们仍然受制于许多相同的规则(特别是当类模板的方法和朋友分别被实例化,给每个方法自己的“实例化状态”)。对于这种情况,标准本身慢慢地使用了更精确的语言,这在一定程度上是由constexpr(如果引入模板语句)(因为它们必须单独实例化,以便只对一个分支进行实例化)所引起的,即使没有语句模板也是如此。(对这些结构来说,可能对进一步研究有用的较旧术语是“temploids”)。
https://stackoverflow.com/questions/67307554
复制相似问题