我更喜欢在单独的文件中编写类和函数模板的定义,该文件自动包含在" public"之后。头。但是,我发现了一个有趣的案例,看起来我无法做到这一点。
template <typename T>
class Outer
{
public:
template <typename U>
class Inner
{
friend bool operator ==(const Inner& lhs, const Inner& rhs);
};
};
using Type = Outer<int>::Inner<short>;
int main()
{
Type a;
Type b;
a == b;
}
是否可以单独编写operator==
的定义,适用于任何T
和U
?
答案 0 :(得分:2)
对于特定的专业化,是的:
template <typename T>
class Outer
{
public:
template <typename U>
class Inner
{
int x = 42;
friend bool operator ==(const Inner& lhs, const Inner& rhs);
};
};
using Type = Outer<int>::Inner<short>;
bool operator ==(const Type& lhs, const Type& rhs) {
return lhs.x == rhs.x;
}
int main()
{
Type a;
Type b;
a == b;
}
在您的示例中,模板的每个特化都是一个非模板函数,它将该特定的特化作为参数。您可以在类中定义此函数(然后每次实例化时都会标记它),或者您可以在类外定义它 - 但是您必须为您使用的每个特化定义一个。
答案 1 :(得分:1)
正如Igor Tandetnik所指出的,你的例子声明了一个非模板友元函数,你必须为每个模板实例化重载,这是允许朋友函数内联定义的一个原因(所以它们可以是由模板生成而不必是模板本身。)
如果您想将朋友功能定义为模板,这是我能够提出的最接近的:
template <typename T>
struct Outer {
template <typename U>
struct Inner;
};
template<typename T, typename U>
bool operator==( typename Outer<T>::template Inner<U> const &, typename Outer<T>::template Inner<U> const & );
template <typename T>
template <typename U>
struct Outer<T>::Inner {
friend bool operator==<T,U>(Inner const &, Inner const &);
};
template<typename T, typename U>
bool operator==( typename Outer<T>::template Inner<U> const &, typename Outer<T>::template Inner<U> const & ) {
return true;
}
// I switched this out, because my gcc-4.6 doesn't
// understand "using" aliases like this yet:
typedef Outer<int>::Inner<short> Type;
int main() {
Type a;
Type b;
operator==<int,short>( a, b );
}
不幸的是,您会注意到此运算符函数的调用站点非常笨拙:operator==<int,short>( a, b )
。我认为在这样的嵌套类模板上定义函数模板会禁用(或至少干扰)参数推导,因此您必须明确指定模板参数(这意味着将其称为函数而不是运算符形式)。这就是内联好友定义如此方便的原因。如果您真的想单独定义operator==
代码,我建议您定义friend
内联来调用另一个函数模板(使用正确的模板参数),您可以然后将外线定义为自由函数。