簡體   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