考虑简单程序:
template<typename T> struct foo{
friend void bar(){}
};
int main(){
foo<int>(); foo<float>();
}
上面的代码打破了ODR规则,我想知道为什么? ,还有函数范围bar
?
答案 0 :(得分:1)
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>();
}
答案 1 :(得分:1)
因为你的代码定义了两次自由函数void bar()
,或者更确切地说,你的模板为每个实例化生成了一个名为void bar()
的新函数,它恰好每次具有完全相同的签名,因此你有多个具有相同签名的功能,这违反了ODR。
手头的技术称为“朋友名称注入”,因为您在周围的命名空间中注入了一个名称。
答案 2 :(得分:0)
您bar
内的struct
已定义。这导致bar
func的双重定义,每个模板实例化一次。 Friend
应该只是某个实体的声明。实体本身(在您的情况下为func)应该在别处定义。将bar
定义替换为friend void bar();
声明,并在另一个地方定义bar
。