Home > Blockchain >  Overloading the output operator for a template class and a nested class
Overloading the output operator for a template class and a nested class

Time:08-12

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

Compiler Explorer

  • Related