【问题标题】:Friend template function in-class definitionFriend模板函数类内定义
【发布时间】:2014-12-11 08:30:39
【问题描述】:

我不知道,为什么 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。

问题是由我的回答引起的:In-class friend operator doesn't seem to participate in overload resolution,答案中有引用标准,指出这样的定义应该在类范围内,如果函数不是模板 - gcc 拒绝这个代码,那是对的。感谢您的回答,以及证明 gcc 正确(或不正确)的标准引用。

【问题讨论】:

    标签: c++ c++11 gcc language-lawyer


    【解决方案1】:

    我会说 GCC 错误地接受了这一点。引用 C++11,强调我的:

    命名空间成员资格,7.3.1.2/3

    在命名空间中首先声明的每个名称都是该命名空间的成员。 如果 friend 声明在非本地 class 首先声明一个类或函数友元类或函数是最内层的成员 命名空间。 通过非限定查找 (3.4.1) 或限定查找 (3.4.3) 无法找到朋友的名称,直到在该命名空间范围内(在类定义之前或之后)提供了匹配的声明 给予友谊)。 如果一个友元函数被调用,它的名字可以通过名字查找找到 来自与函数参数类型关联的命名空间和类的函数 (3.4.2)。 ...

    依赖于参数的查找,3.4.2/2:

    对于函数调用中的每个参数类型T,都有一组零个或多个关联的命名空间和一个 要考虑的零个或多个相关类的集合。确定命名空间和类的集合 完全由函数参数的类型(以及任何模板模板参数的命名空间)决定。 用于指定类型的 Typedef 名称和 using-declarations 不构成该集合。该套 命名空间和类的确定方式如下:

    • ...
    • 如果T 是枚举类型,则其关联的命名空间就是定义它的命名空间。如果是 类成员,其关联的类是该成员的类; 否则它没有关联的类。
    • ...

    3.4.2/4:

    在考虑关联的命名空间时,查找与执行的查找相同 关联命名空间用作限定符(3.4.3.2),除了:

    • ...
    • 任何命名空间范围的友元函数或友元函数模板在关联类中声明 在它们各自的命名空间中可见,即使它们在普通查找期间不可见 (11.3)。
    • ...

    基于上述,我推断FooValueTFooValueT::ONEFooValueT::TWO 的类型)有:: 作为关联的命名空间,但没有关联的类(因为它是一个枚举)。因此,在 ADL 期间不应考虑类模板ImplAdd 中定义的友元函数。

    【讨论】:

    • 感谢您的出色回答。
    • 第一个引用在这里并不重要。您可能需要 7.3.1.2 [namespace.memdef]/p3:“如果非本地类中的友元声明首先声明了一个类或函数,则友元类或函数是最内层封闭命名空间的成员。友元的名称在该命名空间范围内(在授予友谊的类定义之前或之后)提供匹配声明之前,未通过非限定查找 (3.4.1) 或限定查找 (3.4.3) 找不到。"
    • @T.C.很好的发现,谢谢!我知道有一段更直接地解决了这个问题,但我不记得在哪里。我会添加它。
    猜你喜欢
    • 1970-01-01
    • 2012-04-26
    • 1970-01-01
    • 2016-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多