类模板的友元函数

我有一个课程模板
Foo<T>
。 我想实现一个非成员函数
Bar
,需要两个
Foo
s并返回一个
Foo
。我希望
Bar
成为非会员,因为呼叫者写
Bar(f1, f2)
比ѭ6更自然。我也希望
Bar
inline
因为计算是微不足道的。
template <typename T>
inline Foo<T> Bar(const Foo<T> &lhs, const Foo<T> &rhs) {
  ...
}
诀窍是
Bar
需要访问
Foo
的私人数据。我不希望拥有私有数据的访问者 - 没有充分的理由将私有数据暴露给用户。所以我想让
Bar
成为
Foo
的朋友。
template <typename T>
class Foo {
  ...
  private:
    T w, x, y, z;
    friend Foo<T> Bar(const Foo<T> &lhs, const Foo<T> &rhs);
};
这是我遇到麻烦的地方。编译器抱怨:   当友元声明引用功能模板的特化时,不能使用内联说明符。 这个规则是由标准强加的还是特定于MSVC ++? 这是我尝试过的: 使
Bar
成为const公共成员函数,然后声明一个只返回
lhs.Bar(rhs)
的非成员版本。这似乎是最不讨厌的解决方案。 删除
inline
提示,知道编译器将决定内联而不管提示。这是否会违反单一定义规则?它仍然必须在头文件中定义,因为它是一个函数模板。 使用虚拟模板类型声明成员函数:
template <typename T>
class Foo {
  ...
  private:
    T w, x, y, z;

    // Note that this declaration doesn't actually use Dummy.  It's just there to
    // satisfy the compiler.     
    template <typename Dummy>
    friend Foo<T> Bar(const Foo<T> &lhs, const Foo<T> &rhs);
};
我不完全确定为什么会这样,但它确实满足了编译器。 有更好的解决方案吗?     
已邀请:
如果计算是微不足道的,我会写:
template <typename T>
class Foo {
  ...
  private:
    T w, x, y, z;
  public:
    friend Foo Bar(const Foo &lhs, const Foo &rhs) {
        ...
    }
};
这不会违反ODR - 它是一个具有外部链接的内联函数(3.2 / 5从ODR中排除这一点,但定义相同,7.1.2 / 3表示它是内联的)。 但是,这并没有定义函数模板
Bar<T>
,它只是为
Bar
定义了一组函数重载。可能有一些原因,在问题中没有说明,这意味着这对你不起作用,因为你实际上需要模板。     
我最喜欢选项1:
template <typename T>
inline Foo<T> Bar(const Foo<T> &lhs, const Foo<T> &rhs) {
    return lhs.Bar(rhs);
}

template <typename T>
class Foo {
  ...
    Foo<T> Bar(const Foo<T> &other) const;
  private:
    T w, x, y, z;
};
然后该功能安全地包含在类中,但为方便起见,您提供了一个包装函数。     
Bar是一个模板,因此它也必须是朋友声明中的模板。 您不一定要使用虚拟参数,但可以使用
 template <typename U>
 friend Foo<U> Bar(const Foo<U> &lhs, const Foo<U> &rhs);
你不能在这里使用T作为模板参数,因为范围内已经有一个外部T.     

要回复问题请先登录注册