How to define an ostream function of an inner struct of a templated outer struct?

68 views Asked by At

How can I get this to work? I want to separate the definition and declaration of the friend ostream funciton here.

#include <bits/stdc++.h>
using namespace std;

template <class T>
struct Outer {
    struct Inner {
        T x;
    };
    friend std::ostream& operator<<(std::ostream&, const Inner&);
};

template <class T>
std::ostream& operator<<(std::ostream& os, const Outer<T>::Inner& i) {
    os << "x! " << i.x;
    return os;
}

int main() {
    const Outer<int>::Inner s = {42};
    std::cout << s << "\n";
    return 0;
}

Adding typename as suggested by the error doesn't work too

template <class T>
std::ostream& operator<<(std::ostream& os, const typename Outer<T>::Inner& i) {
    os << "x! " << i.x;
    return os;
}
warning: friend declaration 'std::ostream& operator<<(std::ostream&, const Outer<T>::Inner&)' declares a non-template function [-Wnon-template-friend]
   10 |     friend std::ostream& operator<<(std::ostream&, const Inner&);
      |                                                                ^
<source>:10:64: note: (if this is not what you intended, make sure the function template has already been declared and add '<>' after the function name here)
/opt/compiler-explorer/gcc-13.2.0/bin/../lib/gcc/x86_64-linux-gnu/13.2.0/../../../../x86_64-linux-gnu/bin/ld: /tmp/ccBSBhtj.o: in function `main':
<source>:24: undefined reference to `operator<<(std::ostream&, Outer<int>::Inner const&)'
collect2: error: ld returned 1 exit status
1

There are 1 answers

5
Jarod42 On

With:

template <class T>
std::ostream& operator<<(std::ostream& os, const typename Outer<T>::Inner& i)

T is non deducible.

Separate declaration from definition would not be evident.

Simpler would be

template <class T>
struct Outer {
    struct Inner {
        T x;

        friend std::ostream& operator<<(std::ostream &os, const Inner &i) {
            return os << "x! " << i.x;
        }
    };
};