友元模板函数类定义
Friend template function in-class definition
,为什么gcc编译这段代码
#include <type_traits>
template<class Type, class ValueT>
class ImplAdd
{
template<typename T>
friend typename std::enable_if<std::is_same<T, ValueT>::value, Type>::type
operator+(T, T)
{
return Type{};
}
};
enum class FooValueT { ONE, ZERO };
class Foo : ImplAdd<Foo, FooValueT>
{
public:
Foo() {}
Foo(FooValueT) {}
};
struct A {};
int main()
{
Foo f = FooValueT::ONE + FooValueT::ZERO;
}
Clang和MSVC不编译,在我看来,他们是对的。这是 GCC 编译器中的错误吗?gcc 的版本是 4.8.2。
问题是由我的回答引起的:类中友元运算符似乎不参与重载解决,答案中有标准的引用,指出这样的定义应该在类范围内,如果函数不是模板 - gcc 拒绝这个代码,这是对的。非常感谢您的回答和标准引用,证明 gcc 是正确的(或不是(。
我会说GCC错误地接受了这一点。引用C++11,强调我的:
命名空间成员资格,7.3.1.2/3
在命名空间中首次声明的每个名称都是该命名空间的成员。如果非本地
friend
声明 类优先声明一个类或函数 友元类或函数是最内层封闭的成员 命名空间。非限定查找 (3.4.1( 或限定查找 (3.4.3( 找不到好友的名称,直到在该命名空间范围内(在类定义之前或之后(提供匹配的声明 授予友谊(。如果调用了 friend 函数,则可以通过考虑的名称查找找到其名称 与函数参数的类型关联的命名空间和类中的函数 (3.4.2(。...
依赖于参数的查找,3.4.2/2:
对于函数调用中
T
的每个参数类型,都有一组零个或多个关联的命名空间和一个 要考虑的零个或多个关联类的集合。确定命名空间和类的集合 完全由函数参数的类型(以及任何模板模板参数的命名空间(决定。 用于指定类型的 Typedef 名称和 using-声明对此集合没有贡献。的集合 命名空间和类按以下方式确定:
- 。
- 如果
T
是枚举类型,则其关联的命名空间是在其中定义它的命名空间。如果是 类成员,其关联的类是成员的类;否则它没有关联的类。- 。
3.4.2/4:
考虑关联的命名空间时,查找与在 关联的命名空间用作限定符 (3.4.3.2(,但以下情况除外:
- 。
- 在关联类中声明的任何命名空间范围的友元函数或友元函数模板都是 在各自的命名空间中可见,即使在普通查找期间它们不可见 (11.3(。
- 。
基于上述,我推断FooValueT
(FooValueT::ONE
和FooValueT::TWO
的类型(已::
为关联的命名空间,但没有关联的类(因为它是枚举(。因此,在 ADL 期间,不应考虑类模板ImplAdd
中定义的友元函数。
- 在命名空间中定义函数还是限定函数
- 为什么在定义函数之前先声明它
- 使用用户定义函数的字符串反转
- 用户定义函数中的指针和输入
- 这个c++代码是如何在没有定义函数的情况下运行的
- 具有外部"c"和程序集的未定义函数
- 已定义函数时出现 G++ "未定义的引用"错误
- 将自定义函数传递到基抽象类中以延迟执行
- C++使用 rand 定义函数语法
- Arduino:在 loop() 和自定义函数中运行相同的代码时出现问题
- 将具有固定签名的自定义函数名称注入 CRTP
- 使用定义函数模板别名
- 是否可以使用单个定义定义函数的常量和常规版本?(使用模板,自动,decltype等)
- 在内联程序集中定义函数和从 C++ 调用时出现问题
- 在 Metal 着色器代码中,如何定义函数的 in/out 参数变量?
- 声明和定义函数静态会产生"undefined reference to function_name()"
- 朋友定义函数的名称空间是什么
- 介子 对用户定义函数的未定义引用
- 如何使用 "using" 关键字定义函数原型/签名
- 在 C 结构中定义C++函数