我有一个模板类,它仅对用户界面函数使用模板参数,并在内部将数据保存在示例中的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
答案 0 :(得分:0)
那么为什么这不是用类内部编译的, 并在课外编译。
当你有这个:
template <typename T> struct C {
template<typename U>
friend bool operator == (C const& c1, C<U> const& c2)
{
return c1.i == c2.i;
}
};
C<int>() == C<char>()
在::operator==
的外部范围内生成了两个class C
,在我们的例子中是全局命名空间:::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>
的朋友,所以编译时错误。
但是如果你写这样的代码:
template <typename T> struct C {
template<typename U1, typename U>
friend bool operator == (C<U1> const& c1, C<U> const& c2);
private:
int i;
};
template<typename U1, typename U>
bool operator == (C<U1> const& c1, C<U> const& c2)
{
return c1.i == c2.i;
}
其中operator==
未在C
内实现,则编译器不生成operator==
超出其已使用的类C
的范围,
所以我们::operator==<int, char>
这两个类的朋友C<int>
和C<char>
。最后当你有:
template <typename T> struct C {
template<typename U1, typename U>
friend bool operator == (C<U1> const& c1, C<U> const& c2) {
return c1.i == c2.i;
}
private:
int i;
};
在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节。