模板结构外部的重载运算符

Overloading operator outside template struct

本文关键字:重载 运算符 外部 结构      更新时间:2023-10-16

我有以下代码:

#include <iostream>
#include <stdio.h>
using namespace std;
template <class F>
struct CMPLX {
    F Re, Im;
    struct _printnice {
        F Re, Im;
        string sep;
        _printnice(const F& Re, const F& Im, const string& sep) : Re(Re), Im(Im), sep(sep) {}
    };
    CMPLX <F> (F Re, F Im) : Re(Re), Im(Im) {}
    _printnice PrintNice(const string& sep="t"){
        return _printnice(Re, Im, sep);
    }
};
template<class F>
ostream& operator << (ostream& os, const CMPLX<F> c){
    cout << c.Re << " + " << c.Im << "i";
}
template<class F>
ostream& operator << (ostream& os, const CMPLX<F> :: _printnice p){
    cout << p.Re << p.sep << p.Im;
}
int main(){
    CMPLX<float> c(2.0,1.0);
    cout << c << endl;
    cout << c.PrintNice() << endl;
}

我引入了一个子结构_printnice,以便重载运算符<<并具有不同格式的CMPLX类输出。但是,这会引发错误在"p"之前预期非限定 id,我不知道如何解决这个问题(我对模板的了解非常有限)。

我尝试将<<的第二个定义更改为以下有效的定义,但我必须指定类型,这是不受欢迎的:

ostream& operator << (ostream& os, const CMPLX <float> :: _printnice p){
    cout << p.Re << p.sep << p.Im;
}

您的方法有两个问题。首先是_printnice是一个依赖名称,因此您需要添加一个额外的typename .如果修复了这个问题,你最终会得到:

template<class F>
ostream& operator << (ostream& os, typename CMPLX<F>::_printnice const & p)

正如 Dietmar 在之前的回答中指出的那样,此代码的问题在于F处于不可推导的上下文中,这将失败。

一个简单的解决方案是在_printnice代码范围内定义运算符,其中typename

template <class F>
struct CMPLX {
   //...
   struct _printnice {
      friend std::ostream& operator<<( std::ostream& o, _printnice const & p ) {
         // print here
         return o;
      }
   }
   //...
};

_printnice的定义中,已知类型是一个类型,因此不再需要typename。重载operator<<将由参数相关查找找到,并且由于它引用了类型的此特定实例化,因此没有要推断的模板参数。

在函数中:

template <typename F>
std::ostream& operator<<( std::ostream& os, CMPLX<F>::_printnice p);

F并非不在可推导的上下文中。 (参见 §14.8.2.5。

注意。这不是一个答案。大卫已经回答了。FWIW,只是修复了一些东西,所以它可以在gcc 4.72下编译和运行。

#include <iostream>
#include <stdio.h>
using namespace std;
template <class F>
struct CMPLX {
    F Re, Im;
    struct _printnice {
        F Re, Im;
        string sep;
        _printnice(const F& Re, const F& Im, const string& sep) : Re(Re), Im(Im), sep(sep) {}
        friend ostream& operator << (ostream& os, const _printnice& p){
            cout << p.Re << p.sep << p.Im;
            return os;
        }
    };
    CMPLX <F> (F Re, F Im) : Re(Re), Im(Im) {}
    _printnice PrintNice(const string& sep="t"){
        return _printnice(Re, Im, sep);
    }
};
template<class F>
ostream& operator << (ostream& os, const CMPLX<F> c){
    cout << c.Re << " + " << c.Im << "i";
    return os;
}
int main() {
    CMPLX<float> c(2.0,1.0);
    cout << c << endl;
    cout << c.PrintNice() << endl;
}
//result
/*
2 + 1i
2       1
*/