模板中定义的好友功能的实例化 [英] Instantiation of friend function defined inside a template

查看:48
本文介绍了模板中定义的好友功能的实例化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是此问题的后续内容.最初的情况是另外一回事,但是在我写一个差劲的答案和澄清OP的过程中,事实证明,我们可能需要语言律师的帮助才能了解正在发生的事情.

This is a follow up of this question. The original case was something else, but in the course of me writing a poor answer and OP clarifying, it turned out that we probably need the help of a language-lawyer to understand what is going on.

在C ++中的思考-实用程序编程第2卷中,可以找到以下示例(意图矿,在线

In Thinking in C++ - Practical Programming Vol 2 one can find the following example (intendation mine, online here):

//: C05:FriendScope3.cpp {-bor}
// Microsoft: use the -Za (ANSI-compliant) option
#include <iostream>
using namespace std;
 
template<class T> class Friendly {
    T t;
public:
    Friendly(const T& theT) : t(theT) {}
    friend void f(const Friendly<T>& fo) {
        cout << fo.t << endl;
    }
    void g() { f(*this); }
};
 
void h() {
    f(Friendly<int>(1));
}
 
int main() {
    h();
    Friendly<int>(2).g();
} ///:~

他们继续解释(强调我的观点):

They continue to explain (emphasize mine):

此示例与上一个示例之间有一个重要区别: f在这里不是模板,而是普通函数.(请记住,在用括号括起来之前必须暗示f()是模板.)每次实例化Friendly类模板时,都会创建一个新的,普通的函数重载,该重载使用当前参数作为参数.友好的专业化.这就是丹·萨克斯(Dan Saks)所谓的结交新朋友.[68]这是为模板定义好友功能的最便捷方法.

There is an important difference between this and the previous example: f is not a template here, but is an ordinary function. (Remember that angle brackets were necessary before to imply that f( ) was a template.) Every time the Friendly class template is instantiated, a new, ordinary function overload is created that takes an argument of the current Friendly specialization. This is what Dan Saks has called making new friends. [68] This is the most convenient way to define friend functions for templates.

到目前为止,一切都很好.令人困惑的部分是"f在这里不是模板,而是普通函数".+每次实例化Friendly类模板时,都会创建一个新的,普通的函数重载".当您考虑以下示例时:

So far so good. The puzzling part is "f is not a template here, but is an ordinary function" + "Every time the Friendly class template is instantiated, a new, ordinary function overload is created" when you consider this example:

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 ):

Instantiating foo<int> does not cause a compiler error! Only calling bar(x) causes (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>&&'

实例化一个普通函数?那只有在调用函数时才会失败吗?这是怎么回事?

Instantiation of an ordinary function? That only fails when the function is called? What is going on here?

bar 真的是普通功能吗?它仅在被调用时实例化吗?为什么是普通功能?实例化 foo< int> 时,关于 bar 的实际情况是什么(作者称其为创建了一个新的,普通的函数重载",不确定那是什么)应该是这个意思)?

Is bar really an ordinary function? It is only instantiated when called? Why, when it is an ordinary function? What is actually happening with respect to bar when foo<int> is instantiated (the authors call it "a new, ordinary function overload is created", not sure what that is supposed to mean)?

对不起,对于许多人来说,这太令人费解了.并且请不要错过 language-lawyer 标签,我想知道标准的原因/原因,而不只是原因.

Sorry for the many ?s, its just too puzzling. And please don't miss the language-lawyer tag, I want to know the why / what parts of the standard make it so, not just the what.

PS:请确保我再次检查,当不调用 bar 时,三个通常的嫌疑人都在没有重大抱怨的情况下编译了该示例:

PS: Just to be sure I checked again and the three usual suspects all compile the example without major complaints when bar is not called: https://godbolt.org/z/Wcsbc5qjv

推荐答案

[temp.inst]/2 :类模板特殊化的隐式实例化导致声明的隐式实例化,而不是定义,默认参数或 noexcept-specifiers 班上的...朋友...

[temp.inst]/2 The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions, default arguments, or noexcept-specifiers of the class ... friends...

[temp.inst]/4 ...当在需要存在函数定义的上下文中引用该函数时,从朋友函数定义实例化其声明的函数将被隐式实例化.

[temp.inst]/4 ... A function whose declaration was instantiated from a friend function definition is implicitly instantiated when it is referenced in a context that requires a function definition to exist...

这篇关于模板中定义的好友功能的实例化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆