以下代码编译得很好(只是一个最小的例子,实际代码有更多这种特定布局的原因):
template<int A>
class Foo {
template<int B>
friend int bar(Foo<A> a, Foo<B> b) {
return A * B;
}
};
int main() {
return bar(Foo<0>(), Foo<1>());
}
但是,我想将声明与定义分开,并将函数定义放在类定义之外。我已经尝试过像成员函数一样:
template<int A> template<int B>
int bar(Foo<A> a, Foo<B> b) {
return A * B;
}
但是无法编译,因为它似乎不是有效的语法:
error: too many template-parameter-lists
但是,合并此定义中的两个模板参数列表(template<int A, int B>
)会产生链接器错误:
undefined reference to `int bar<1>(Foo<0>, Foo<1>)'
这让我相信不同的模板参数列表会导致编译器/链接器将bar
的定义解释为与声明不同的函数。
所以我的问题是:当类和函数有单独的模板参数时,如何在类定义之外定义友元函数?
答案 0 :(得分:2)
我认为没有办法做到这一点。那么有但不是一般的。您始终可以为每个A
显式写入重载:
template<int B>
int bar(Foo<0> a, Foo<B> b) {
return 0 + B;
}
基本上,原因是为bar
的每个实例化定义了不同的Foo
重载。例如,对于Foo<0>
,您将获得
template<int B>
int bar(Foo<0>, Foo<B>);
对于Foo
的每个实例,您将获得一个新的bar
模板。所有这些bar
都是独立的,因为它们使用的模板参数存在于bar
之外(来自外部模板)。
您不能使用双template<>
语法,因为这意味着您有两个作为模板的东西(类,函数,...)。这不是这种情况,因为您只有bar
作为模板。第一个/第二个template<>
没有其他内容。
你无法合并它们,因为如你所见,你将获得不同的功能。如果您查看bar
上方的实例化Foo<0>
,您会发现这与以下内容不同:
template<int A, int B>
int bar(Foo<A>, Foo<B>);
实例化版本总是更好的匹配,因为它不必为第一个参数推导出任何东西。