There is a template class in which a subclass is nested. How to properly overload the output operator to the stream for an external class, which is a template, in which the output operator to the stream is called from a nested class? In my case, compilation errors occur:
no type named 'type' in 'struct std::enable_if<false, void>'
no match for 'operator<<' (operand types are 'std::basic_ostream' and 'Nesting::Nested')
I give my code below.
#include <iostream>
#include <string>
using namespace std;
template<typename T>
class Nesting {
public:
class Nested {
public:
T data;
Nested(const T & data): data(data) {;}
template<typename U>
friend ostream & operator<<(ostream & out, const typename Nesting<U>::Nested & nested);
};
T data;
Nested * pNested;
Nesting(const T & data)
: data(data)
, pNested(new Nested(222)) {;}
template<typename U>
friend ostream & operator<<(ostream & out, const Nesting<U> & nesting);
};
template<typename T>
ostream & operator<<(ostream & out, const typename Nesting<T>::Nested & nested) {
out << "Nested: " << nested.data;
return out;
}
template<typename T>
ostream & operator<<(ostream & out, const Nesting<T> & nesting) {
out << "Nesting: " << nesting.data << ", " << *nesting.pNested << endl;
return out;
}
int main() {
Nesting<int> n(111);
cout << n << endl;
return 0;
}
CodePudding user response:
I think the easiest thing to do is to provide the definition inline with the declaration.
#include <iostream>
#include <memory>
#include <string>
using std::cout;
using std::make_unique;
using std::ostream;
using std::unique_ptr;
template<typename T>
class Nesting {
public:
class Nested {
public:
T data;
Nested(T const& data_): data{data_} {}
friend auto operator<<(ostream& out, Nested const& nested) -> ostream& {
return out << "Nested: " << nested.data;
}
};
T data;
unique_ptr<Nested> pNested;
Nesting(T const& data_)
: data{data_}
, pNested{make_unique<Nested>(222)} {}
friend auto operator<<(ostream& out, Nesting const& nesting) -> ostream& {
return out << "Nesting: " << nesting.data << ", " << *nesting.pNested;
}
};
int main() {
Nesting<int> n(111);
cout << n << "\n";
}
CodePudding user response:
You can add a wrapper to remove the dependant type deduction. Something like:
template<typename T>
struct NestingNested
{
const Nesting<T>::Nested & nested;
template<typename U>
friend std::ostream & operator<<(std::ostream & out, const NestingNested<U> & nested);
};
template<typename T>
std::ostream & operator<<(std::ostream & out, const NestingNested<T> & nested) {
out << "Nested: " << nested.nested.data;
return out;
}
template<typename T>
std::ostream & operator<<(std::ostream & out, const Nesting<T> & nesting) {
out << "Nesting: " << nesting.data << ", " << NestingNested<T>{ *nesting.pNested } << std::endl;
return out;
}