【问题标题】:How to befriend one instantiation of template class with other one of the same template如何使模板类的一个实例与同一模板的另一个实例成为朋友
【发布时间】:2015-10-25 15:00:08
【问题描述】:

我有一个模板类,它仅将模板参数用于用户界面功能,并在内部将数据保存在某些字段中,例如示例中的ii 的类型没有被模板化。所有实例化必须协同工作并访问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

【问题讨论】:

  • 你最近不是问过同样的问题吗?
  • 干得好,你发现了一个 Clang 错误 AFAICS。
  • 毕竟,看起来您要求的是 XY 问题。您能否详细说明您需要这个的实际用例。
  • 如果您不能信任了解正在发生的事情并对您的代码发表评论的人,那么您作为 stackoverflow 主问者的运营商将不会太成功。
  • 我移动模板 bool operator == (C const& c2) const noexcept { return i == c2.i; } 到公共部分,所有编译都可以使用 gcc 5.2/clang 3.7

标签: c++ templates c++14


【解决方案1】:

那么为什么不使用类内部编译, 并在课堂外编译。

当你有这个时:

  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==&lt;char&gt;(C&lt;int&gt; const&amp; c1, C&lt;char&gt; const&amp; c2)(1) 和 ::operator==&lt;int&gt;(C&lt;char&gt; const&amp; c1, C&lt;int&gt; const&amp; c2)(2),第一个是C&lt;int&gt;的朋友,第二个是C&lt;char&gt;的朋友。编译器使用(1)。 (1) 是C&lt;int&gt; 的唯一朋友所以编译时出错。

但是如果你写这样的代码:

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 内部实现,那么编译器不会在它使用的类C 的范围之外生成operator== 它已经存在, 所以我们有::operator==&lt;int, char&gt;C&lt;int&gt;C&lt;char&gt; 这两个班级的哪个朋友。最后,当你有:

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&lt;int&gt;() == C&lt;char&gt;() 的情况下,您有两个由::operator== ::operator==&lt;int&gt;(C&lt;int&gt;const&amp;, C&lt;char&gt;const&amp;)::operator==&lt;char&gt;(C&lt;int&gt;const&amp;, C&lt;char&gt;const&amp;) 和编译器应该在此处生成编译时错误。

参考 c++11 标准最后草案,第 14.5.4 和 11.3.5 节。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多