【问题标题】:Overload operator<< for template class模板类的重载运算符<<
【发布时间】:2012-12-31 08:31:55
【问题描述】:

我在为模板类重载 operator

#ifndef _FINITEFIELD
#define _FINITEFIELD
#include<iostream>

namespace Polyff{
    template <class T, T& n> class FiniteField;
    template <class T, T& n> std::ostream& operator<< (std::ostream&, const FiniteField<T,n>&);

    template <class T, T& n> class FiniteField {
    public:
            //some other functions
    private:
        friend std::ostream& operator<< <T,n>(std::ostream& out, const FiniteField<T,n>& obj);
        T _val;
    };

    template <class T, T& n>
    std::ostream& operator<< (std::ostream& out, const FiniteField<T,n>& f) {
        return  out<<f._val;
    }
    //some other definitions
}
#endif

主要我只有

#include"FiniteField.h"
#include"Integer.h"
#include<iostream>
using std::cout;
using namespace Polyff;
Integer N(5);

int main () {

    FiniteField<Integer, N> f1;
    cout<< f1;  
}

其中Integer 只是int 的包装,具有我需要的一些特殊功能。

但是,当我编译上面的代码时,我得到了错误 C2679,上面写着binary '&lt;&lt;' : no operator found which takes a right-hand operand of type 'Polyff::FiniteField&lt;T,n&gt;' (or there is no acceptable conversion)

我也试过去掉朋友声明中的参数,所以代码变成:

friend std::ostream& operator<< <> (std::ostream& out, const FiniteField<T,n>& obj);

但这会产生另一个错误:C2785: 'std::ostream &amp;Polyff::operator &lt;&lt;(std::ostream &amp;,const Polyff::FiniteField&lt;T,n&gt; &amp;)' and '&lt;Unknown&gt;' have different return types

所以我想知道我应该如何更改代码才能编译,为什么? 谢谢!

------------------------- 编辑于 2012.12.31 ----------------- ----------

代码现在用 g++ 编译。 Here 是 github 仓库。

【问题讨论】:

  • 虽然我不完全确定 T& 的用途是什么,但我不确定它是否重要。我只用Polyff::FiniteField&lt;int,N&gt; obj 尝试了您的第一个代码列表,其中 N 是全局int。当我然后cout &lt;&lt; obj &lt;&lt; endl; 时,它工作正常(逐步调试以确保)。你的 Integer 类可能有问题吗? (顺便说一下,在 Mac OS X 10.8.1 上使用 LLVM 4.1)。
  • 感谢您的建议。我刚刚用 int 测试过,还是不行。但是,当我尝试使用 g++ 编译器编译我的代码时,一切正常,我的 Integer 包装器类也是如此。这是 vs2010 编译器的一些错误吗?顺便说一句,参数“T&N”是建立在它所基于的积分域上的有限域的上限。如果你不知道我在说什么并且觉得它很烦人,你可以通过搜索“有限域”找到更多相关信息。
  • Clang++ 和 G++ 都可以编译它(在添加了 Integer 的定义和 FiniteField 的默认构造函数之后,您应该包含它以使代码完整和独立)。注: _FINITEFIELDreserved name,为您的包含保护选择不同的宏。
  • 如果你使用 Polyff::operator
  • 这将是有线的,因为g++ 能够推断出如何引用operator&lt;&lt;。我想我只会认为这是 VS2010 编译器的错误。顺便说一句,这个程序只是我对 C++ 模板的小尝试,不是一个严肃项目的任何部分。感谢大家的帮助!

标签: c++ visual-studio-2010 templates operator-overloading friend-function


【解决方案1】:

这似乎按预期工作:

namespace Polyff{
  template <class T, T* n> class FiniteField;
  template <class T, T* n> std::ostream& operator<< (std::ostream&, const FiniteField<T,n>&);

  template <class T, T* n> class FiniteField {
  public:
    //some other functions
  private:
    friend std::ostream& operator<< <T,n>(std::ostream& out, const FiniteField<T,n>& obj);
    T _val;
  };

  template <class T, T* n>
  std::ostream& operator<< (std::ostream& out, const FiniteField<T,n>& f) {
    return  out << f._val.n; // I added the field of my Integer class
  }
  //some other definitions
}


struct Integer{
  Integer() : n(0){}
  Integer(int nn) : n(nn){}
  int n;
};

using std::cout;
using namespace Polyff;
Integer N(5);

int main () {
  FiniteField<Integer, &N> f1;
  cout<< f1;  
}

我只是用模板参数中的对象指针替换了引用,因为指向全局对象(静态或非静态)的指针是编译时(或至少链接时)已知的信息。我不知道接受参考的语言。

请注意,在此示例中,0 将被打印,因为它对应于 _val 的默认构造。

【讨论】:

    【解决方案2】:

    我试图在我的 Visual C++ 2010 上编译你的代码。我得到了和你一样的错误。

    Visual 在您的代码中实际上有两件事不喜欢:

    1. N 不是编译时间常数(这是对的,不是吗?)。
    2. 然后问题是获取编译时间常数的引用。因此,您应该在所有模板参数中将“T& n”替换为“T n”。

    这让我有了这份工作!

    【讨论】:

    • 其实非类型参数也可以是外部链接的变量或函数的地址,此类参数参与推演。看起来像 VC 中的问题
    • 感谢您的回答!但是我确实认为对N 的引用是一个编译时常量,因为该对象是在静态内存中分配的。否则,g++ 也不应该能够编译。至于第二条评论,当你将T &amp;n 切换为T n 时,你是否使用int 作为T
    • 这就是我所做的:用 int 替换 Int(不是用 int 替换 T)并报告错误。然后,我删除了模板参数中的“&”。 VC 抱怨 N 不是编译时间常数。然后我定义了一个宏来替换 N 并编译它。我在模板参数中添加了“&”,而 VC 抱怨引用该引用。所以,VC 的抱怨 2 实际上是以宏的使用为条件的(我应该更准确地说,对不起)。
    • 感谢您的回复。您是否建议解决此问题?或者,我仍然不明白这如何解释 VC 编译器的行为。
    【解决方案3】:

    您应该将引用替换为普通变量(T n 而不是 T&amp; n)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-05
      • 1970-01-01
      • 1970-01-01
      • 2021-09-19
      • 2016-04-21
      • 2011-04-30
      • 2013-03-24
      • 2019-01-14
      相关资源
      最近更新 更多