【问题标题】:Define friend function outside class definition when the class and function have separate template parameters当类和函数具有单独的模板参数时,在类定义之外定义友元函数
【发布时间】:2018-05-01 08:20:19
【问题描述】:

下面的代码编译得很好(只是一个最小的例子,实际的代码有更多的原因是这种特殊的布局):

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&lt;int A, int B&gt;) 会导致链接器错误:

undefined reference to `int bar<1>(Foo<0>, Foo<1>)'

这让我相信不同的模板参数列表会导致编译器/链接器将bar 的定义解释为与声明不同的函数。

所以我的问题是:当类和函数具有单独的模板参数时,如何在类定义之外定义友元函数?

【问题讨论】:

  • 明确一点:即使单个template 函数定义紧跟类模板定义(在同一个文件中),也会发生链接器错误?
  • @Angew 是的,我将所有代码放在同一个文件中以测试我的最小示例
  • 我认为 Rakete1111 的回答是正确的。所以...对解决方法感兴趣? wandbox.org/permlink/jrHIq5sSSQ8lUPYd
  • @bogdan 目前我的代码中只有一个短函数存在这个问题,所以我不想为此添加大量样板。我可能会将定义留在类定义中或使其成为成员函数。由于所讨论的函数是operator*,因此其余代码是否使用朋友或成员函数并不重要。

标签: c++ templates friend


【解决方案1】:

我认为没有办法做到这一点。嗯,但不是一般的。您始终可以为每个 A 显式编写重载:

template<int B>
int bar(Foo<0> a, Foo<B> b) {
    return 0 + B;
}

基本上,原因是为Foo 的每个实例定义了不同的bar 重载。例如,对于Foo&lt;0&gt;,您将获得一个

template<int B>
int bar(Foo<0>, Foo<B>);

对于Foo 的每个实例化,您将获得一个新的bar 模板。所有这些bars 都是独立的,因为它们使用存在于bar 本身之外的模板参数(来自外部模板)。

您不能使用双重template&lt;&gt; 语法,因为这意味着您有两个作为模板的东西(类、函数...)。这不是这里的情况,因为您只有 bar 作为模板。第一个/第二个template&lt;&gt;没有别的了。

您无法合并它们,因为正如您所见,您将获得不同的功能。如果您查看上面为Foo&lt;0&gt; 实例化的bar,您会发现它不同于:

template<int A, int B>
int bar(Foo<A>, Foo<B>);

实例化的版本总是更好的匹配,因为它不需要为第一个参数推导任何东西。

【讨论】:

  • 但是bar 是所有Foo&lt;A&gt; 实例化的朋友,而不仅仅是用作第一个参数的那个。
  • @cp.fe.cp 哦,所以你有一些 bar 不应该访问的专业?在这种情况下,您可以删除特定的 bar 重载。
  • 它是如何工作的? bar 是否仍然可以访问 b 的私​​有成员,而原始代码中不是这种情况?
  • @cp.fe.cp 是的,bar 可以访问 b(以及 a)的私有成员,但您发布的代码也是如此。
  • 我发布的代码不是这样,只有a 的私人成员可以访问(给定A != B)。 Click here for example code.
猜你喜欢
  • 2016-10-19
  • 2011-05-16
  • 1970-01-01
  • 2016-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多