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 introduce a sub-struct _printnice
in order to overload the operator <<
and have differently-formatted output of my CMPLX
class. However, this throws an error expected unqualified-id before 'p' and I don't know how to solve this (my knowledge on templates is very limited).
I try to change the 2nd definition of <<
to the following which works, but I have to specify the type, which is frowned-upon:
ostream& operator << (ostream& os, const CMPLX <float> :: _printnice p){
cout << p.Re << p.sep << p.Im;
}
There are two issues with your approach. The first is that _printnice
is a dependent name and as such you need to add an extra typename
. If that were fixed you would end up with:
template<class F>
ostream& operator << (ostream& os, typename CMPLX<F>::_printnice const & p)
The problem with this code, as Dietmar pointed out in a previous answer, is that F
is in a non deducible context, and this will fail.
One simple solution is to define the operator inside the scope of the _printnice
code, where the typename
:
template <class F>
struct CMPLX {
//...
struct _printnice {
friend std::ostream& operator<<( std::ostream& o, _printnice const & p ) {
// print here
return o;
}
}
//...
};
Inside the definition of _printnice
, the type is known to be a type and thus the typename
is no longer required. The overloaded operator<<
will be found by Argument Dependent Lookup, and because it refers to this particular instantiation of the type, there is no template arguments to deduce.
In the function:
template <typename F>
std::ostream& operator<<( std::ostream& os, CMPLX<F>::_printnice p);
F
is not not in a deducible context. (See §14.8.2.5.)
NB. This is not a answer. David answered it already. FWIW, just fixed a few things so it can compile & runable 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
*/
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.