首页 文章

如何与模板类的一个实例化与同一模板中的另一个实例化

提问于
浏览
1

我有一个模板类,它仅将模板参数用于用户界面函数,并在内部将数据保存在某些字段中,如示例中的 i . i 的类型不是模板化的 . 所有实例化必须一起工作并访问 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

1 回答

  • 0

    那么为什么这个没有编译成类的内部,并在类外编译 .

    当你有这个:

    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>()
    

    class C 的外部范围内生成了两个 ::operator== ,在我们的全局命名空间中: ::operator==<char>(C<int> const& c1, C<char> const& c2) (1)和 ::operator==<int>(C<char> const& c1, C<int> const& c2) (2),第一个是 C<int> 的朋友,第二个是朋友 C<char> . 编译器使用(1) . (1)只是 C<int> 的朋友,所以编译时错误 .

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

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

    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<int>() == C<char>() 的情况下,您有两个由 ::operator== ::operator==<int>(C<int>const&, C<char>const&)::operator==<char>(C<int>const&, C<char>const&) 的编译器变体生成,编译器应该在这里生成编译时错误 .

    参考文献c 11标准最后草案,第14.5.4和11.3.5节 .

相关问题