Operator overload outside template structure

I have the following code:

#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; } 

I present the _printnice substructure in order to overload the << operator and have a result with a different format for my CMPLX class. However, this causes the expected unqualified-id before 'p to fail, and I don't know how to solve this (my knowledge of templates is very limited).

I am trying to change the second definition of << to the following, which works, but I have to specify the type that frowned:

 ostream& operator << (ostream& os, const CMPLX <float> :: _printnice p){ cout << p.Re << p.sep << p.Im; } 
+4
source share
3 answers

There are two problems in your approach. Firstly, _printnice is a dependent name, and so you need to add an extra typename . If this were fixed, you would receive:

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

The problem with this code, as Dietmar noted in the previous answer, is that F is in an undetectable context, and this will not work.

One simple solution is to define a statement inside the _printnice code _printnice , where typename :

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

Inside the _printnice definition _printnice type is known as a type, and therefore typename no longer required. An overloaded operator<< will be found depending on the dependencies of the argument, and since it refers to this particular instance of the type, there are no template arguments to output.

+4
source

In function:

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

F not in the output context. (See §14.8.2.5.)

+1
source

NB. This is not an answer. David already answered. FWIW just fixed a few things so that it could compile and work under 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 */ 
0
source

Source: https://habr.com/ru/post/1439864/


All Articles