14

C++03和C++11在[temp.friend]的第一段中有:

[编辑引用。第一次尝试错过了措辞的第二个差异。]

对于不是模板声明的友元函数声明:

  1. 如果朋友的名字是合格或不合格的 template-id,朋友声明是指一个函数模板的特化,否则

  2. 如果朋友的名字是一个qualified-id,并且在指定的类或命名空间中找到了一个匹配的非模板函数,朋友声明引用那个函数,否则,

  3. [C++03:] 如果朋友的名字是一个qualified-id,并且在指定的类或命名空间中找到了一个函数模板的匹配特化,则朋友声明引用该函数模板特化,否则,

    [C++11:] 如果朋友的名字是一个qualified-id,并且在指定的类或命名空间中找到了一个匹配的函数模板,朋友声明是指该函数模板的推导特化,否则,

  4. 该名称应为声明(或重新声明)普通(非模板)函数的非限定 ID 。

[措辞的变化对我来说似乎是澄清。虽然我猜可能有不同的方式来解释 C++03 中关于“在类或命名空间中寻找专业化”的措辞。]

我对第三颗子弹很好奇。我编写此代码以尝试满足其要求,但 g++ 4.8.1 和 clang++ 3.4 都拒绝该代码,无论是使用 -std=c++03 还是 -std=c++11:

template <class T> class R;
namespace N {
    template <class T> void test(const R<T>&);
}

template <class T>
class R {
    friend void N::test(const R<T>&);  // 8
    int m;
};

template <class T>
void N::test(const R<T>& rec) { rec.m; }

int main() {
    R<int> r;
    N::test(r);
}

当然,如果我将第 8 行更改为

friend void N::test<>(const R<T>&);

第一个项目符号适用并且程序被接受。g++ 打印一个有用的警告,说朋友“声明了一个非模板函数”,并建议我可能想要这样做。为了清晰和安全,代码可能会获得更多样式点。

但是上面的代码不应该被第三个项目符号覆盖并且有效吗?朋友声明不是模板声明,它使用不是模板ID 的限定ID作为名称。并且没有与第二个项目符号匹配的非模板函数声明。

这只是两者共同的编译器错误吗?或者我是否误解了某些东西,如果是这样,是否有一个程序示例可以演示第三个项目符号?

4

3 回答 3

1

在第 //8 行,修改代码为: friend void N::test< R<T> >( R<T>&); 也正确。

friend void N::test<R<T>>(const R<T>&);//one type is friend with one type  #1
friend void N::test<>(const R<T>&);// one type is friend with one type    #2

我使用一些代码证明 #1 等于 #2

最后,我试着回答你的问题。我不确定这是对的。

 friend void N::test(const R<T>&);

当实例化类 R 时,R<T>是一个已知类型。但是,函数是

声明为友元函数并且真的不实例化函数模板,那么

朋友功能是一个不存在的功能。从语法的角度来看,

编译器会提示你它是一个函数而不是一个模板

N::test (r);

在这个地方实例化了函数,但编译器不匹配

在 R 类中声明之前的朋友,因为您没有在 R 中声明为模板

类,你只需声明一个函数。

于 2014-11-17T10:22:40.347 回答
0

我认为 <> 是进行扣除的条件,因为从 14.8.2.6 开始,

在其 declarator-id 指代函数模板的特化的声明中,执行模板参数推导以识别该声明所指的特化。具体来说,这是针对显式实例化 (14.7.2)、显式特化 (14.7.3) 和某些友元声明 (14.5.4) 完成的。

在这种情况下,declarator-id 不是特化,因此不会进行推导。

于 2013-10-24T16:52:03.020 回答
0

N::test 是一个模板函数,它接受一个名为T. 它不需要一个名为R<T>. 适当地更改功能,它将起作用。

namespace N
{
    template <class T>
    void test ( const T & );
}

template <class T>
class R
{
    friend void N::test ( const R<T> & );
    int m;
};

template <class T>
void N::test ( const T & rec ) { rec.m; }

int main ( )
{
    R<int> r;
    N::test ( r );
}
于 2014-09-07T20:08:09.387 回答