繁体   English   中英

有定义的朋友 function - 模板还是非模板?

[英]Friend function with a definition - template or non-template?

假设我们有以下代码:

template<class T> struct S;
template<class T> void operator++(S<T>);

template<class T> struct S {
    friend void operator++(S);
};

template<class T>
void operator++(S<T>) {}

int main() {
    S<int> s;
    ++s;
}

这将编译但不会链接,因为friend声明引入了一个从未定义过的非模板operator++

这个常见问题解答的内容如下(粗体是我的):

解决方案是在编译器检查 class 主体时说服编译器operator++ function 本身就是一个模板 做这件事有很多种方法;

第一种方法是在朋友声明中加入<> ,这里不考虑。 第二个是“在class体内定义朋友function”:

template<class T> struct S {
    friend void operator++(S) { }
};

引用表明void operator++(S)现在是 function 模板,而不是非模板 function。 是吗?

它不是模板,因为它的声明不是模板的声明(即使它出现在模板声明本身中)。

[temp.friend] (强调我的)

1 A friend of a class or class template can be a function template or class template, a specialization of a function template or class template, or a non-template function or class. 对于不是模板声明的朋友 function 声明

  • 如果朋友的名字是合格或不合格的模板ID,朋友声明指的是function模板的特化,否则,

  • 如果朋友的名字是qualified-id并且在指定的class或命名空间中找到匹配的非模板function,则朋友声明指的是function,否则

  • 如果朋友的名字是一个qualified-id并且匹配的function模板在指定的class或命名空间中找到,朋友声明是指推导出的那个ZC1C425268E68385D1AB5074C17A9模板的特化,否则[decFlZA4]

  • 该名称应为声明(或重新声明)非模板 function 的非限定 ID

[ 例子:

 template<class T> class task; template<class T> task<T>* preempt(task<T>*); template<class T> class task { friend void next_time(); friend void process(task<T>*); friend task<T>* preempt<T>(task<T>*); template<class C> friend int func(C); friend class task<int>; template<class P> friend class frd; };

这里,任务 class 模板的每个特化都有 function next_time作为好友; 因为process没有明确的模板参数,任务 class 模板的每个特化都有一个适当类型的 function process作为朋友,而这个朋友不是 ZC1C425268E68385D1AB5074C17A94F 因为朋友preempt有一个明确的模板参数Ttask class 模板的每个特化都有 function 模板作为朋友preempt的适当特化; 并且task class 模板的每个特化具有func模板的所有特化作为朋友。 类似地, task class 模板的每个特化具有 class 模板特化task<int>作为好友,并且具有 class 模板frd的所有特化作为好友。 —结束示例]

虽然示例是非规范性的,但引文中的示例阐明了前述规范性文本的意图。 由于友元运算符声明不是模板声明,因此适用粗体文本。 因此它声明了一个非模板 function。

template<class T> struct S {
    friend void operator++(S s) { }
};

operator ++不再是模板。

对于更常规的 function ( operator用法与函数略有不同),它可能允许扣除:

template<class T> struct S {
    S(T t);
    friend void foo(S lhs, S rhs) { }
};

template <typename T>
void bar(S<T> s, T t)
{
    foo(s, t);   // would not work if foo was template, would require foo<T>(s, t);
    foo(s, {t}); // would not work if foo was template, would require foo<T>(s, {t});
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM