为什么我不能在模板化类中内联定义非模板化友元?
Why can't I inline-define a non-templated friend within a templated class?
mcve的说话胜于雄辩:
// int bar();
template <bool B> class Foo {
friend int ::bar() { return 123; }
};
int main()
{
Foo<false> f1;
Foo<true> f2;
}
使用GCC 6和--std=c++14
,这给了我:
a.cpp: In instantiation of ‘class Foo<true>’:
a.cpp:9:12: required from here
a.cpp:3:13: error: redefinition of ‘int bar()’
friend int ::bar() { return 123; }
^~
a.cpp:3:13: note: ‘int bar()’ previously defined here
现在,我不确定标准怎么说;但是我知道编译器知道朋友没有在B
上模板,其定义也不使用B
。那么,为什么它不能应用"哦,函数相同定义的所有内联副本都是相同的"规则?
现在,我不确定标准怎么说;
实际上已经在即将到来的C 17
中阐明了一个示例。[temp.inst]/2类模板专业化的隐式实例... [snip] ...为了确定成员的实例化重新分支是否有效,根据3.2 [basic.def.odr]和9.2 [class.mem],与模板中定义相对应的声明被认为是一个定义。[示例:
... [SNIP(另一个示例)] ...
template<typename T> struct Friendly { template<typename U> friend int f(U) { return sizeof(T); } }; Friendly<char> fc; Friendly<float> ff; // ill-formed: produces second definition of f(U)
- 结束示例]
诚然,正如您指出的那样,标准的示例确实为每个实例化产生了不同的定义,但这对于示例并不需要根据该规则进行不良。blockquote> 那么,为什么不能应用"哦,函数相同定义的所有内联副本都是相同的"规则? 这个问题似乎也适用于更简单的情况: 肯定可以看到定义是相同的,就像编译器可以看到 然而,ODR说重新定义是不明式的。对于类模板之外的定义以及由类模板的实例化引起的定义是正确的。 也许ODR 可以放松您所证明的情况,但这需要使用特殊案例规则使标准复杂化,并使编译器复杂化,然后必须分析是否使用模板参数在定义中,因此这种放松当然并非没有妥协。inline void foo(){}
inline void foo(){}
::bar
的定义不取决于Foo
的模板参数。
相关文章:
- 在模板类之外定义友元函数的正确方法是什么?
- 2个模板化类的非模板友元函数未定义引用错误
- 未定义的类模板不会实例化以检查友元函数
- 在类内定义的友元函数与类外定义的友元函数的查找规则之间的差异
- 具有定义模板还是非模板的友元函数
- 为什么T是未定义的?我正在尝试实现一个用于双链表的节点类,它不喜欢我使用友元运算符后的T
- 模板和隐式构造函数的类定义之外的友元声明
- 为什么我不能定义一元运算符,然后在 MSVC 的模板类中声明具有相同名称的友元二进制运算符?
- 为什么在定义类之前声明类的对象会在友元类中给出错误,而在友元函数中不会出错
- 正确的友元定义,以授予 std::map 对私有默认构造函数的访问权限
- 如何获取指向模板类中定义的友元函数的函数指针
- 在 c++ 中定义命名空间中模板类的友元函数时出现问题
- 当类和函数具有单独的模板参数时,在类定义之外定义友元函数
- 获取内联定义的友元函数的地址
- 我可以有一个从外部不可见但未在标头中定义的静态友元函数吗?
- 如何正确定义无友元函数
- 如何在局部类中定义友元函数运算符>>?
- 在类中定义友元用户定义的文字运算符
- 在类内定义友元函数模板的情况下,如何避免重定义错误
- c++必须在头文件中定义友元函数