我有一个模板类,它仅将模板参数用于用户界面函数,并在内部将数据保存在某些字段中,如示例中的 i
. i
的类型不是模板化的 . 所有实例化必须一起工作并访问 i
,但不能从模板的用户外部访问 i
. 问题是如何结交同一模板的不同实例 . 他们必须访问其他实例化的私有数据,并且在内部所有这些实例化都是相同的 .
假设,我想比较模板的不同实例,如下例所示 . 这里 i
用于实例化其他模板参数是私有的,如果我尝试声明这个模板 friend
,它不起作用 . 我知道,我可以在类模板之外定义 operator ==
,但是假设我需要做一些函数,比如 is_same
,它必须是一个成员,我希望它的主体在类声明中 .
#include <iostream>
template<typename T>
class C
{
template<typename U> // ????????
friend class C;
template<typename U>
friend bool operator == (C const& c1, C<U> const& c2) noexcept
{
return c1.i == c2.i;
}
int i;
public:
C(): i {0} {}
C(int val): i {val} {}
template<typename U>
bool is_same(C<U> const& c)
{
return c.i == i;
}
}; // template class C
int main()
{
C<int> c1 {5};
C<char> c2 {5};
if (c1 == c2) std::cout << "All ok" << std::endl;
else std::cout << "Very bad" << std::endl;
if (c1.is_same(c2)) std::cout << "All ok" << std::endl;
else std::cout << "Very bad" << std::endl;
return 0;
}
编译错误(gcc 5.1 -std = c 14)
~/main.cpp:15:9: error: «int C<char>::i» is private
1 回答
那么为什么这个没有编译成类的内部,并在类外编译 .
当你有这个:
在
class C
的外部范围内生成了两个::operator==
,在我们的全局命名空间中:::operator==<char>(C<int> const& c1, C<char> const& c2)
(1)和::operator==<int>(C<char> const& c1, C<int> const& c2)
(2),第一个是C<int>
的朋友,第二个是朋友C<char>
. 编译器使用(1) . (1)只是C<int>
的朋友,所以编译时错误 .但是如果你编写这样的代码:
其中
operator==
未在C
内实现,那么编译器不会生成operator==
范围之外的C
它使用已经存在,所以我们有::operator==<int, char>
这两个类的朋友C<int>
和C<char>
. 最后当你有:在
C<int>() == C<char>()
的情况下,您有两个由::operator==
::operator==<int>(C<int>const&, C<char>const&)
和::operator==<char>(C<int>const&, C<char>const&)
的编译器变体生成,编译器应该在这里生成编译时错误 .参考文献c 11标准最后草案,第14.5.4和11.3.5节 .