#include <iostream>

template<class T1, class T2>
class TwoThings {
    T1 thing1;
    T2 thing2;
    TwoThings(T1 t1, T2 t2) : thing1(t1), thing2(t2)
       template<class T3, class T4>
       friend std::ostream& operator<<(std::ostream& os, const TwoThings<T3, T4)&);

template<class T1, class T2>
std::ostream&::operator<<(std::ostream& os, const TwoThings<T1, T2>& tt)
                                        std::cout<<tt.thing1<<' '<<tt.thing2;
                                        return os;

int main()
    int a = 123;
    double b = 455.789;
    TwoThings<int, double> my_twothings(a, b);
    std::cout<< my_twothings << std::endl;
    return 0;

everytime i try to compile it i get his error, as if the compiler cannot find the definition for it:

Linking console executable: bin\Debug\Frozen.exe
Error: Unresolved external 'std::basic_ostream<char, std::char_traits<char> >& operator <<(std::basic_ostream<char, std::char_traits<char> >&, const TwoThings<int, double>&)' referenced from C:\FROZEN\OBJ\DEBUG\MAIN.OBJ
Process terminated with status 2 (0 minutes, 0 seconds)
0 errors, 0 warnings

i checked and for some reason if i make this function inline it works.
I am confused i can't find the typo i made here and i got this example out of the book, anyone notice what i did wrong?

Anyone see the error? I know its probably so obvious but i can't find it.

Inside the class declaration is a typo, change to ..

template<class T3, class T4> friend std::ostream & operator<<(std::ostream& os, const TwoThings<T3, T4> &);

And then the definition without the scope resolution operator

template<class T3, class T4> std::ostream & operator<<(std::ostream & os, const TwoThings<T3, T4> & tt)
    std::cout<<tt.thing1<<' '<<tt.thing2;
    return os;

When in doubt, a good place to get a 'second opinion' about a given piece of code is the Comeau's Test Drive Comeau C++ Online. It is supposed to be a very standards-compliant compiler and tends to produce quite understandable error messages.