重複の可能性:
インライン フレンド関数の範囲は?
簡単なプログラムを考えてみましょう:
template<typename T> struct foo{
friend void bar(){}
};
int main(){
foo<int>(); foo<float>();
}
上記のコードは ODR ルールに違反しています。なぜでしょうか? 、また、機能の範囲はどこbar
ですか?
重複の可能性:
インライン フレンド関数の範囲は?
簡単なプログラムを考えてみましょう:
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>();
}
あなたのコードは free 関数void bar()
を 2 回定義しているため、つまり、テンプレートはインスタンス化ごとに という名前の新しい関数を生成し、毎回void bar()
まったく同じシグネチャを持っているため、同じシグネチャを持つ複数の関数があり、これは違反です。 ODRの。
周囲の名前空間に名前を挿入するため、当面の手法は「Friend Name Injection」と呼ばれます。
の内部を定義しました。これにより、テンプレートのインスタンス化ごとに1回、funcが二重に定義されます。あるエンティティの宣言にすぎないはずです。エンティティ自体(あなたの場合はfunc)は他の場所で定義する必要があります。定義を宣言に置き換えて、別の場所で定義してください。bar
struct
bar
Friend
bar
friend void bar();
bar