可能重複:
What’s the scope of inline friend functions?什麼/哪裏是在類模板中定義的朋友函數定義的範圍?
考慮簡單的程序:
template<typename T> struct foo{
friend void bar(){}
};
int main(){
foo<int>(); foo<float>();
}
以上代碼打破了ODR規則,我不知道爲什麼? ,功能bar
的功能範圍在哪裏?
可能重複:
What’s the scope of inline friend functions?什麼/哪裏是在類模板中定義的朋友函數定義的範圍?
考慮簡單的程序:
template<typename T> struct foo{
friend void bar(){}
};
int main(){
foo<int>(); foo<float>();
}
以上代碼打破了ODR規則,我不知道爲什麼? ,功能bar
的功能範圍在哪裏?
friend
函數不是成員函數;你只需在類中聲明友誼,但函數總是一個自由函數。如果你在一個類模板類中定義它,你將最終定義它作爲模板實例的次數。
我會盡力用代碼解釋。對於我們來說,你的代碼是相同的:
template<typename T> struct foo{
};
template<> struct foo<int>{
friend void bar();
};
void bar() {};
template<> struct foo<double>{
friend void bar();
};
void bar() {};
int main(){
foo<int>(); foo<float>();
}
你有定義bar
在你的struct
裏面。這導致bar
func的雙重定義,每個模板實例化一次。 Friend
應該只是某個實體的聲明。實體本身(你的情況下的函數)應該在其他地方定義。將您的bar
定義替換爲friend void bar();
聲明並在另一個地方定義您的bar
。
請再讀一遍這個問題,當然在同一個單元裏有兩個def但是bar的範圍是什麼? – M3taSpl0it
因爲你的代碼定義的自由功能void bar()
兩次,或讓寧說,你的模板會爲每一個實例化一個新功能名爲void bar()
,這恰好有每次完全相同的簽名,因此您有多個具有相同簽名的功能,這是違反ODR的。
手頭的技術被稱爲「朋友名注入」,因爲您將名稱注入到周圍的名稱空間中。
所以'bar'的範圍在上述情況下是全局範圍? – M3taSpl0it
是的,全球範圍。 – Gorpik